Skip to content

Commit de278b4

Browse files
Prepend prefix for MAR operations (#1741)
1 parent 8a339b0 commit de278b4

8 files changed

+111
-7
lines changed

src/code/ContainerRegistryServerAPICalls.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,8 @@ public override Stream InstallPackage(string packageName, string packageVersion,
286286
return results;
287287
}
288288

289-
results = InstallVersion(packageName, packageVersion, out errRecord);
289+
string packageNameForInstall = PrependMARPrefix(packageName);
290+
results = InstallVersion(packageNameForInstall, packageVersion, out errRecord);
290291
return results;
291292
}
292293

@@ -1601,13 +1602,14 @@ private Hashtable[] FindPackagesWithVersionHelper(string packageName, VersionTyp
16011602
string registryUrl = Repository.Uri.ToString();
16021603
string packageNameLowercase = packageName.ToLower();
16031604

1605+
string packageNameForFind = PrependMARPrefix(packageNameLowercase);
16041606
string containerRegistryAccessToken = GetContainerRegistryAccessToken(out errRecord);
16051607
if (errRecord != null)
16061608
{
16071609
return emptyHashResponses;
16081610
}
16091611

1610-
var foundTags = FindContainerRegistryImageTags(packageNameLowercase, "*", containerRegistryAccessToken, out errRecord);
1612+
var foundTags = FindContainerRegistryImageTags(packageNameForFind, "*", containerRegistryAccessToken, out errRecord);
16111613
if (errRecord != null || foundTags == null)
16121614
{
16131615
return emptyHashResponses;
@@ -1616,7 +1618,7 @@ private Hashtable[] FindPackagesWithVersionHelper(string packageName, VersionTyp
16161618
List<Hashtable> latestVersionResponse = new List<Hashtable>();
16171619
List<JToken> allVersionsList = foundTags["tags"].ToList();
16181620

1619-
SortedDictionary<NuGet.Versioning.SemanticVersion, string> sortedQualifyingPkgs = GetPackagesWithRequiredVersion(allVersionsList, versionType, versionRange, requiredVersion, packageNameLowercase, includePrerelease, out errRecord);
1621+
SortedDictionary<NuGet.Versioning.SemanticVersion, string> sortedQualifyingPkgs = GetPackagesWithRequiredVersion(allVersionsList, versionType, versionRange, requiredVersion, packageNameForFind, includePrerelease, out errRecord);
16201622
if (errRecord != null)
16211623
{
16221624
return emptyHashResponses;
@@ -1627,7 +1629,7 @@ private Hashtable[] FindPackagesWithVersionHelper(string packageName, VersionTyp
16271629
foreach (var pkgVersionTag in pkgsInDescendingOrder)
16281630
{
16291631
string exactTagVersion = pkgVersionTag.Value.ToString();
1630-
Hashtable metadata = GetContainerRegistryMetadata(packageNameLowercase, exactTagVersion, containerRegistryAccessToken, out errRecord);
1632+
Hashtable metadata = GetContainerRegistryMetadata(packageNameForFind, exactTagVersion, containerRegistryAccessToken, out errRecord);
16311633
if (errRecord != null || metadata.Count == 0)
16321634
{
16331635
return emptyHashResponses;
@@ -1694,6 +1696,18 @@ private Hashtable[] FindPackagesWithVersionHelper(string packageName, VersionTyp
16941696
return sortedPkgs;
16951697
}
16961698

1699+
private string PrependMARPrefix(string packageName)
1700+
{
1701+
string prefix = string.IsNullOrEmpty(InternalHooks.MARPrefix) ? PSRepositoryInfo.MARPrefix : InternalHooks.MARPrefix;
1702+
1703+
// If the repostitory is MAR and its not a wildcard search, we need to prefix the package name with MAR prefix.
1704+
string updatedPackageName = Repository.IsMARRepository() && packageName.Trim() != "*"
1705+
? string.Concat(prefix, packageName)
1706+
: packageName;
1707+
1708+
return updatedPackageName;
1709+
}
1710+
16971711
#endregion
16981712
}
16991713
}

src/code/InternalHooks.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class InternalHooks
1515

1616
internal static string AllowedUri;
1717

18+
internal static string MARPrefix;
19+
1820
public static void SetTestHook(string property, object value)
1921
{
2022
var fieldInfo = typeof(InternalHooks).GetField(property, BindingFlags.Static | BindingFlags.NonPublic);

src/code/PSRepositoryInfo.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ namespace Microsoft.PowerShell.PSResourceGet.UtilClasses
1111
/// </summary>
1212
public sealed class PSRepositoryInfo
1313
{
14+
#region constants
15+
internal const string MARPrefix = "psresource/";
16+
#endregion
17+
1418
#region Enums
1519

1620
public enum APIVersion
@@ -95,5 +99,14 @@ public enum RepositoryProviderType
9599
public bool IsAllowedByPolicy { get; set; }
96100

97101
#endregion
102+
103+
#region Methods
104+
105+
internal bool IsMARRepository()
106+
{
107+
return (ApiVersion == APIVersion.ContainerRegistry && Uri.Host.Contains("mcr.microsoft.com"));
108+
}
109+
110+
#endregion
98111
}
99112
}

src/code/PublishHelper.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,17 @@ internal void PushResource(string Repository, string modulePrefix, bool SkipDepe
368368
return;
369369
}
370370

371+
if (repository.IsMARRepository())
372+
{
373+
_cmdletPassedIn.WriteError(new ErrorRecord(
374+
new PSInvalidOperationException($"Repository '{repository.Name}' is a MAR repository and cannot be published to."),
375+
"MARRepositoryPublishError",
376+
ErrorCategory.PermissionDenied,
377+
this));
378+
379+
return;
380+
}
381+
371382
_networkCredential = Utils.SetNetworkCredential(repository, _networkCredential, _cmdletPassedIn);
372383

373384
// Check if dependencies already exist within the repo if:

src/code/RepositorySettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ private static PSRepositoryInfo.APIVersion GetRepoAPIVersion(Uri repoUri)
862862
// repositories with Uri Scheme "temp" may have PSPath Uri's like: "Temp:\repo" and we should consider them as local repositories.
863863
return PSRepositoryInfo.APIVersion.Local;
864864
}
865-
else if (repoUri.AbsoluteUri.EndsWith(".azurecr.io") || repoUri.AbsoluteUri.EndsWith(".azurecr.io/"))
865+
else if (repoUri.AbsoluteUri.EndsWith(".azurecr.io") || repoUri.AbsoluteUri.EndsWith(".azurecr.io/") || repoUri.AbsoluteUri.Contains("mcr.microsoft.com"))
866866
{
867867
return PSRepositoryInfo.APIVersion.ContainerRegistry;
868868
}
@@ -876,7 +876,7 @@ private static RepositoryProviderType GetRepositoryProviderType(Uri repoUri)
876876
{
877877
string absoluteUri = repoUri.AbsoluteUri;
878878
// We want to use contains instead of EndsWith to accomodate for trailing '/'
879-
if (absoluteUri.Contains("azurecr.io")){
879+
if (absoluteUri.Contains("azurecr.io") || absoluteUri.Contains("mcr.microsoft.com")){
880880
return RepositoryProviderType.ACR;
881881
}
882882
// TODO: add a regex for this match

test/FindPSResourceTests/FindPSResourceContainerRegistryServer.Tests.ps1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,21 @@ Describe 'Test HTTP Find-PSResource for ACR Server Protocol' -tags 'CI' {
228228
$res.Type.ToString() | Should -Be "Script"
229229
}
230230
}
231+
232+
Describe 'Test Find-PSResource for MAR Repository' -tags 'CI' {
233+
BeforeAll {
234+
[Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("MARPrefix", "azure-powershell/");
235+
Register-PSResourceRepository -Name "MAR" -Uri "https://mcr.microsoft.com" -ApiVersion "ContainerRegistry"
236+
}
237+
238+
AfterAll {
239+
[Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("MARPrefix", $null);
240+
Unregister-PSResourceRepository -Name "MAR"
241+
}
242+
243+
It "Should find resource given specific Name, Version null" {
244+
$res = Find-PSResource -Name "Az.Accounts" -Repository "MAR"
245+
$res.Name | Should -Be "Az.Accounts"
246+
$res.Version | Should -Be "3.0.4"
247+
}
248+
}

test/InstallPSResourceTests/InstallPSResourceContainerRegistryServer.Tests.ps1

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ Describe 'Test Install-PSResource for ACR scenarios' -tags 'CI' {
137137

138138
It "Install resource with a dependency (should install both parent and dependency)" {
139139
Install-PSResource -Name $testModuleParentName -Repository $ACRRepoName -TrustRepository
140-
140+
141141
$parentPkg = Get-InstalledPSResource $testModuleParentName
142142
$parentPkg.Name | Should -Be $testModuleParentName
143143
$parentPkg.Version | Should -Be "1.0.0"
@@ -307,3 +307,28 @@ Describe 'Test Install-PSResource for V3Server scenarios' -tags 'ManualValidatio
307307
Set-PSResourceRepository PoshTestGallery -Trusted
308308
}
309309
}
310+
311+
Describe 'Test Install-PSResource for MAR Repository' -tags 'CI' {
312+
BeforeAll {
313+
[Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("MARPrefix", "azure-powershell/");
314+
Register-PSResourceRepository -Name "MAR" -Uri "https://mcr.microsoft.com" -ApiVersion "ContainerRegistry"
315+
}
316+
317+
AfterAll {
318+
[Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("MARPrefix", $null);
319+
Unregister-PSResourceRepository -Name "MAR"
320+
}
321+
322+
It "Should find resource given specific Name, Version null" {
323+
try {
324+
$pkg = Install-PSResource -Name "Az.Accounts" -Repository "MAR" -PassThru -TrustRepository -Reinstall
325+
$pkg.Name | Should -Be "Az.Accounts"
326+
$pkg.Version | Should -Be "3.0.4"
327+
}
328+
finally {
329+
if ($pkg) {
330+
Uninstall-PSResource -Name "Az.Accounts" -Version "3.0.4"
331+
}
332+
}
333+
}
334+
}

test/PublishPSResourceTests/PublishPSResourceContainerRegistryServer.Tests.ps1

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,3 +512,24 @@ Describe "Test Publish-PSResource" -tags 'CI' {
512512
$results[0].Version | Should -Be $version
513513
}
514514
}
515+
516+
Describe 'Test Publish-PSResource for MAR Repository' -tags 'CI' {
517+
BeforeAll {
518+
[Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("MARPrefix", "azure-powershell/");
519+
Register-PSResourceRepository -Name "MAR" -Uri "https://mcr.microsoft.com" -ApiVersion "ContainerRegistry"
520+
}
521+
522+
AfterAll {
523+
[Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("MARPrefix", $null);
524+
Unregister-PSResourceRepository -Name "MAR"
525+
}
526+
527+
It "Should find resource given specific Name, Version null" {
528+
$fileName = "NonExistent.psd1"
529+
$modulePath = New-Item -Path "$TestDrive\NonExistent" -ItemType Directory -Force
530+
$psd1Path = Join-Path -Path $modulePath -ChildPath $fileName
531+
New-ModuleManifest -Path $psd1Path -ModuleVersion "1.0.0" -Description "NonExistent module"
532+
533+
{ Publish-PSResource -Path $modulePath -Repository "MAR" -ErrorAction Stop } | Should -Throw -ErrorId "MARRepositoryPublishError,Microsoft.PowerShell.PSResourceGet.Cmdlets.PublishPSResource"
534+
}
535+
}

0 commit comments

Comments
 (0)