diff --git a/src/code/ContainerRegistryServerAPICalls.cs b/src/code/ContainerRegistryServerAPICalls.cs index 54f3cb714..0edb24bb8 100644 --- a/src/code/ContainerRegistryServerAPICalls.cs +++ b/src/code/ContainerRegistryServerAPICalls.cs @@ -698,37 +698,38 @@ internal JObject FindAllRepositories(string containerRegistryAccessToken, out Er internal Hashtable GetContainerRegistryMetadata(string packageName, string exactTagVersion, string containerRegistryAccessToken, out ErrorRecord errRecord) { _cmdletPassedIn.WriteDebug("In ContainerRegistryServerAPICalls::GetContainerRegistryMetadata()"); - Hashtable requiredVersionResponse = new Hashtable(); + Hashtable requiredVersionResponse = new(); - var foundTags = FindContainerRegistryManifest(packageName, exactTagVersion, containerRegistryAccessToken, out errRecord); + JObject foundTags = FindContainerRegistryManifest(packageName, exactTagVersion, containerRegistryAccessToken, out errRecord); if (errRecord != null) { return requiredVersionResponse; } - /* Response returned looks something like: - * { - * "schemaVersion": 2, - * "config": { - * "mediaType": "application/vnd.unknown.config.v1+json", - * "digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - * "size": 0 - * }, - * "layers": [ - * { - * "mediaType": "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip'", - * "digest": "sha256:7c55c7b66cb075628660d8249cc4866f16e34741c246a42ed97fb23ccd4ea956", - * "size": 3533, - * "annotations": { - * "org.opencontainers.image.title": "test_module.1.0.0.nupkg", - * "metadata": "{\"GUID\":\"45219bf4-10a4-4242-92d6-9bfcf79878fd\",\"FunctionsToExport\":[],\"CompanyName\":\"Anam\",\"CmdletsToExport\":[],\"VariablesToExport\":\"*\",\"Author\":\"Anam Navied\",\"ModuleVersion\":\"1.0.0\",\"Copyright\":\"(c) Anam Navied. All rights reserved.\",\"PrivateData\":{\"PSData\":{\"Tags\":[\"Test\",\"CommandsAndResource\",\"Tag2\"]}},\"RequiredModules\":[],\"Description\":\"This is a test module, for PSGallery team internal testing. Do not take a dependency on this package. This version contains tags for the package.\",\"AliasesToExport\":[]}" - * } - * } - * ] - * } - */ - - var serverPkgInfo = GetMetadataProperty(foundTags, packageName, out errRecord); + /* + Response returned looks something like: + { + "schemaVersion": 2, + "config": { + "mediaType": "application/vnd.unknown.config.v1+json", + "digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "size": 0 + }, + "layers": [ + { + "mediaType": "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip'", + "digest": "sha256:7c55c7b66cb075628660d8249cc4866f16e34741c246a42ed97fb23ccd4ea956", + "size": 3533, + "annotations": { + "org.opencontainers.image.title": "test_module.1.0.0.nupkg", + "metadata": "{\"GUID\":\"45219bf4-10a4-4242-92d6-9bfcf79878fd\",\"FunctionsToExport\":[],\"CompanyName\":\"Anam\",\"CmdletsToExport\":[],\"VariablesToExport\":\"*\",\"Author\":\"Anam Navied\",\"ModuleVersion\":\"1.0.0\",\"Copyright\":\"(c) Anam Navied. All rights reserved.\",\"PrivateData\":{\"PSData\":{\"Tags\":[\"Test\",\"CommandsAndResource\",\"Tag2\"]}},\"RequiredModules\":[],\"Description\":\"This is a test module, for PSGallery team internal testing. Do not take a dependency on this package. This version contains tags for the package.\",\"AliasesToExport\":[]}" + } + } + ] + } + */ + + ContainerRegistryInfo serverPkgInfo = GetMetadataProperty(foundTags, packageName, out errRecord); if (errRecord != null) { return requiredVersionResponse; @@ -738,8 +739,9 @@ internal Hashtable GetContainerRegistryMetadata(string packageName, string exact { using (JsonDocument metadataJSONDoc = JsonDocument.Parse(serverPkgInfo.Metadata)) { - string pkgVersionString = String.Empty; + string pkgVersionString = String.Empty; JsonElement rootDom = metadataJSONDoc.RootElement; + if (rootDom.TryGetProperty("ModuleVersion", out JsonElement pkgVersionElement)) { // module metadata will have "ModuleVersion" property @@ -831,7 +833,7 @@ internal ContainerRegistryInfo GetMetadataProperty(JObject foundTags, string pac errRecord = null; ContainerRegistryInfo serverPkgInfo = null; - var layers = foundTags["layers"]; + JToken layers = foundTags["layers"]; if (layers == null || layers[0] == null) { errRecord = new ErrorRecord( @@ -843,7 +845,7 @@ internal ContainerRegistryInfo GetMetadataProperty(JObject foundTags, string pac return serverPkgInfo; } - var annotations = layers[0]["annotations"]; + JToken annotations = layers[0]["annotations"]; if (annotations == null) { errRecord = new ErrorRecord( @@ -856,7 +858,7 @@ internal ContainerRegistryInfo GetMetadataProperty(JObject foundTags, string pac } // Check for package name - var pkgTitleJToken = annotations["org.opencontainers.image.title"]; + JToken pkgTitleJToken = annotations["org.opencontainers.image.title"]; if (pkgTitleJToken == null) { errRecord = new ErrorRecord( @@ -881,7 +883,7 @@ internal ContainerRegistryInfo GetMetadataProperty(JObject foundTags, string pac } // Check for package metadata - var pkgMetadataJToken = annotations["metadata"]; + JToken pkgMetadataJToken = annotations["metadata"]; if (pkgMetadataJToken == null) { errRecord = new ErrorRecord( @@ -893,10 +895,10 @@ internal ContainerRegistryInfo GetMetadataProperty(JObject foundTags, string pac return serverPkgInfo; } - var metadata = pkgMetadataJToken.ToString(); + string metadata = pkgMetadataJToken.ToString(); // Check for package artifact type - var resourceTypeJToken = annotations["resourceType"]; + JToken resourceTypeJToken = annotations["resourceType"]; var resourceType = resourceTypeJToken != null ? resourceTypeJToken.ToString() : "None"; return new ContainerRegistryInfo(metadataPkgName, metadata, resourceType); diff --git a/src/code/PSResourceInfo.cs b/src/code/PSResourceInfo.cs index 0bc651cf5..baf44ddfb 100644 --- a/src/code/PSResourceInfo.cs +++ b/src/code/PSResourceInfo.cs @@ -1639,10 +1639,10 @@ internal static Dependency[] ParseHttpDependencies(string dependencyString) internal static List ParseContainerRegistryDependencies(JsonElement requiredModulesElement, out string errorMsg) { errorMsg = string.Empty; - List pkgDeps = new List(); + List pkgDeps = new(); if (requiredModulesElement.ValueKind == JsonValueKind.Array) { - foreach (var dependency in requiredModulesElement.EnumerateArray()) + foreach (JsonElement dependency in requiredModulesElement.EnumerateArray()) { if (dependency.ValueKind == JsonValueKind.String) { @@ -1669,15 +1669,16 @@ internal static List ParseContainerRegistryDependencies(JsonElement } depVersionRange = new VersionRange( - minVersion: depNuGetVersion, - includeMinVersion: true); + minVersion: depNuGetVersion, + includeMinVersion: true + ); } else if (dependency.TryGetProperty("RequiredVersion", out JsonElement depRequiredVersionElement)) { // New-ScriptFileInfo will add "RequiredVersion" value as "null" if nothing is explicitly passed in, // Which gets translated to an empty string. // In this case, we just want the VersionRange to be VersionRange.All - if (!string.Equals(depModuleVersionElement.ToString(), string.Empty)) + if (!string.Equals(depRequiredVersionElement.ToString(), string.Empty)) { if (!NuGetVersion.TryParse(depRequiredVersionElement.ToString(), out NuGetVersion depNuGetVersion)) { @@ -1686,10 +1687,11 @@ internal static List ParseContainerRegistryDependencies(JsonElement } depVersionRange = new VersionRange( - minVersion: depNuGetVersion, - includeMinVersion: true, - maxVersion: depNuGetVersion, - includeMaxVersion: true); + minVersion: depNuGetVersion, + includeMinVersion: true, + maxVersion: depNuGetVersion, + includeMaxVersion: true + ); } } diff --git a/test/FindPSResourceTests/FindPSResourceContainerRegistryServer.Tests.ps1 b/test/FindPSResourceTests/FindPSResourceContainerRegistryServer.Tests.ps1 index 824e169c4..ff27ac772 100644 --- a/test/FindPSResourceTests/FindPSResourceContainerRegistryServer.Tests.ps1 +++ b/test/FindPSResourceTests/FindPSResourceContainerRegistryServer.Tests.ps1 @@ -6,7 +6,7 @@ Import-Module $modPath -Force -Verbose Describe 'Test HTTP Find-PSResource for ACR Server Protocol' -tags 'CI' { - BeforeAll{ + BeforeAll { $testModuleName = "test-module" $testModuleWith2DigitVersion = "test-2DigitPkg" $testModuleParentName = "test_parent_mod" @@ -19,13 +19,11 @@ Describe 'Test HTTP Find-PSResource for ACR Server Protocol' -tags 'CI' { $usingAzAuth = $env:USINGAZAUTH -eq 'true' - if ($usingAzAuth) - { + if ($usingAzAuth) { Write-Verbose -Verbose "Using Az module for authentication" Register-PSResourceRepository -Name $ACRRepoName -ApiVersion 'ContainerRegistry' -Uri $ACRRepoUri -Verbose } - else - { + else { $psCredInfo = New-Object Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo ("SecretStore", "$env:TENANTID") Register-PSResourceRepository -Name $ACRRepoName -ApiVersion 'ContainerRegistry' -Uri $ACRRepoUri -CredentialInfo $psCredInfo -Verbose } @@ -51,18 +49,18 @@ Describe 'Test HTTP Find-PSResource for ACR Server Protocol' -tags 'CI' { $res | Should -BeNullOrEmpty } - $testCases2 = @{Version="[5.0.0.0]"; ExpectedVersions=@("5.0.0"); Reason="validate version, exact match"}, - @{Version="5.0.0.0"; ExpectedVersions=@("5.0.0"); Reason="validate version, exact match without bracket syntax"}, - @{Version="[1.0.0.0, 5.0.0.0]"; ExpectedVersions=@("1.0.0", "3.0.0", "5.0.0"); Reason="validate version, exact range inclusive"}, - @{Version="(1.0.0.0, 5.0.0.0)"; ExpectedVersions=@("3.0.0"); Reason="validate version, exact range exclusive"}, - @{Version="(1.0.0.0,)"; ExpectedVersions=@("3.0.0", "5.0.0"); Reason="validate version, minimum version exclusive"}, - @{Version="[1.0.0.0,)"; ExpectedVersions=@("1.0.0", "3.0.0", "5.0.0"); Reason="validate version, minimum version inclusive"}, - @{Version="(,3.0.0.0)"; ExpectedVersions=@("1.0.0"); Reason="validate version, maximum version exclusive"}, - @{Version="(,3.0.0.0]"; ExpectedVersions=@("1.0.0", "3.0.0"); Reason="validate version, maximum version inclusive"}, - @{Version="[1.0.0.0, 5.0.0.0)"; ExpectedVersions=@("1.0.0", "3.0.0"); Reason="validate version, mixed inclusive minimum and exclusive maximum version"} - @{Version="(1.0.0.0, 5.0.0.0]"; ExpectedVersions=@("3.0.0", "5.0.0"); Reason="validate version, mixed exclusive minimum and inclusive maximum version"} + $testCases2 = @{Version = "[5.0.0.0]"; ExpectedVersions = @("5.0.0"); Reason = "validate version, exact match" }, + @{Version = "5.0.0.0"; ExpectedVersions = @("5.0.0"); Reason = "validate version, exact match without bracket syntax" }, + @{Version = "[1.0.0.0, 5.0.0.0]"; ExpectedVersions = @("1.0.0", "3.0.0", "5.0.0"); Reason = "validate version, exact range inclusive" }, + @{Version = "(1.0.0.0, 5.0.0.0)"; ExpectedVersions = @("3.0.0"); Reason = "validate version, exact range exclusive" }, + @{Version = "(1.0.0.0,)"; ExpectedVersions = @("3.0.0", "5.0.0"); Reason = "validate version, minimum version exclusive" }, + @{Version = "[1.0.0.0,)"; ExpectedVersions = @("1.0.0", "3.0.0", "5.0.0"); Reason = "validate version, minimum version inclusive" }, + @{Version = "(,3.0.0.0)"; ExpectedVersions = @("1.0.0"); Reason = "validate version, maximum version exclusive" }, + @{Version = "(,3.0.0.0]"; ExpectedVersions = @("1.0.0", "3.0.0"); Reason = "validate version, maximum version inclusive" }, + @{Version = "[1.0.0.0, 5.0.0.0)"; ExpectedVersions = @("1.0.0", "3.0.0"); Reason = "validate version, mixed inclusive minimum and exclusive maximum version" } + @{Version = "(1.0.0.0, 5.0.0.0]"; ExpectedVersions = @("3.0.0", "5.0.0"); Reason = "validate version, mixed exclusive minimum and inclusive maximum version" } - It "Find resource when given Name to " -TestCases $testCases2{ + It "Find resource when given Name to " -TestCases $testCases2 { # FindVersionGlobbing() param($Version, $ExpectedVersions) $res = Find-PSResource -Name $testModuleName -Version $Version -Repository $ACRRepoName @@ -311,12 +309,23 @@ Describe 'Test Find-PSResource for MAR Repository' -tags 'CI' { $res | Should -Not -BeNullOrEmpty $res.Count | Should -BeGreaterThan 1 } + + It "Should find version range for Az dependencies" { + # Target known version to know the output from the API won't change + $res = Find-PSResource -Repository 'MAR' -Name 'Az' -Version '14.4.0' + + # Version defined by "ModuleVersion" + $res.Dependencies.Where{$_.'Name' -eq 'Az.Accounts'}.'VersionRange'.ToString() | Should -Be '[5.3.0, )' + + # Version defined by "RequiredVersion" + $res.Dependencies.Where{$_.'Name' -eq 'Az.Resources'}.'VersionRange'.ToString() | Should -Be '[8.1.0, 8.1.0]' + } } -# Skip this test fo +# Skip this test for Windows PowerShell Describe 'Test Find-PSResource for unauthenticated ACR repository' -tags 'CI' { BeforeAll { - $skipOnWinPS = $PSVersionTable.PSVersion.Major -eq 5 + $skipOnWinPS = $PSVersionTable.PSVersion.Major -eq 5 if (-not $skipOnWinPS) { Register-PSResourceRepository -Name "Unauthenticated" -Uri "https://psresourcegetnoauth.azurecr.io/" -ApiVersion "ContainerRegistry"