diff --git a/src/code/V3ServerAPICalls.cs b/src/code/V3ServerAPICalls.cs
index a6b8d3620..f425c15e3 100644
--- a/src/code/V3ServerAPICalls.cs
+++ b/src/code/V3ServerAPICalls.cs
@@ -27,6 +27,7 @@ internal class V3ServerAPICalls : ServerApiCall
private bool _isJFrogRepo { get; set; }
private bool _isGHPkgsRepo { get; set; }
private bool _isMyGetRepo { get; set; }
+ private bool _isAWSCodeArtifactRepo { get; set; }
public FindResponseType v3FindResponseType = FindResponseType.ResponseString;
private static readonly Hashtable[] emptyHashResponses = new Hashtable[]{};
private static readonly string nugetRepoUri = "https://api.nuget.org/v3/index.json";
@@ -55,7 +56,7 @@ public V3ServerAPICalls(PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, Ne
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
bool token = false;
- if(networkCredential != null)
+ if(networkCredential != null)
{
token = String.Equals("token", networkCredential.UserName) ? true : false;
};
@@ -71,7 +72,7 @@ public V3ServerAPICalls(PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, Ne
} else {
handler.Credentials = networkCredential;
-
+
_sessionClient = new HttpClient(handler);
};
@@ -80,9 +81,10 @@ public V3ServerAPICalls(PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, Ne
_sessionClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", userAgentString);
_isNuGetRepo = String.Equals(Repository.Uri.AbsoluteUri, nugetRepoUri, StringComparison.InvariantCultureIgnoreCase);
- _isJFrogRepo = Repository.Uri.AbsoluteUri.ToLower().Contains("jfrog.io");
- _isGHPkgsRepo = Repository.Uri.AbsoluteUri.ToLower().Contains("pkg.github.com");
- _isMyGetRepo = Repository.Uri.AbsoluteUri.ToLower().Contains("myget.org");
+ _isJFrogRepo = RepositoryUriContains("jfrog.io");
+ _isGHPkgsRepo = RepositoryUriContains("pkg.github.com");
+ _isMyGetRepo = RepositoryUriContains("myget.org");
+ _isAWSCodeArtifactRepo = RepositoryUriContains(".codeartifact.") && RepositoryUriContains(".amazonaws.com");
}
#endregion
@@ -91,18 +93,37 @@ public V3ServerAPICalls(PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, Ne
///
/// Find method which allows for searching for all packages from a repository and returns latest version for each.
- /// Not supported for V3 repository.
+ /// Supported for AWS CodeArtifact V3 repository only.
///
public override FindResults FindAll(bool includePrerelease, ResourceType type, out ErrorRecord errRecord)
{
_cmdletPassedIn.WriteDebug("In V3ServerAPICalls::FindAll()");
- errRecord = new ErrorRecord(
- new InvalidOperationException($"Find all is not supported for the V3 server protocol repository '{Repository.Name}'"),
- "FindAllFailure",
- ErrorCategory.InvalidOperation,
- this);
- return new FindResults(stringResponse: Utils.EmptyStrArray, hashtableResponse: emptyHashResponses, responseType: v3FindResponseType);
+ if (!_isAWSCodeArtifactRepo)
+ {
+ errRecord = new ErrorRecord(
+ new InvalidOperationException($"Find all is not supported for the V3 server protocol repository '{Repository.Name}'"),
+ "FindAllFailure",
+ ErrorCategory.InvalidOperation,
+ this);
+
+ return new FindResults(stringResponse: Utils.EmptyStrArray, hashtableResponse: emptyHashResponses, responseType: v3FindResponseType);
+ }
+
+ var queryTerm = "";
+ var matchingPkgEntries = GetVersionedPackageEntriesFromSearchQueryResource(queryTerm, includePrerelease, out errRecord);
+ if (errRecord != null)
+ {
+ return new FindResults(stringResponse: Utils.EmptyStrArray, hashtableResponse: emptyHashResponses, responseType: v3FindResponseType);
+ }
+
+ List matchingResponses = new List();
+ foreach (var pkgEntry in matchingPkgEntries)
+ {
+ matchingResponses.Add(pkgEntry.ToString());
+ }
+
+ return new FindResults(stringResponse: matchingResponses.ToArray(), hashtableResponse: emptyHashResponses, responseType: v3FindResponseType);
}
///
@@ -175,7 +196,7 @@ public override FindResults FindNameWithTag(string packageName, string[] tags, b
public override FindResults FindNameGlobbing(string packageName, bool includePrerelease, ResourceType type, out ErrorRecord errRecord)
{
_cmdletPassedIn.WriteDebug("In V3ServerAPICalls::FindNameGlobbing()");
- if (_isNuGetRepo || _isJFrogRepo || _isGHPkgsRepo || _isMyGetRepo)
+ if (_isNuGetRepo || _isJFrogRepo || _isGHPkgsRepo || _isMyGetRepo || _isAWSCodeArtifactRepo)
{
return FindNameGlobbingFromNuGetRepo(packageName, tags: Utils.EmptyStrArray, includePrerelease, out errRecord);
}
@@ -198,7 +219,7 @@ public override FindResults FindNameGlobbing(string packageName, bool includePre
public override FindResults FindNameGlobbingWithTag(string packageName, string[] tags, bool includePrerelease, ResourceType type, out ErrorRecord errRecord)
{
_cmdletPassedIn.WriteDebug("In V3ServerAPICalls::FindNameGlobbingWithTag()");
- if (_isNuGetRepo || _isJFrogRepo || _isGHPkgsRepo || _isMyGetRepo)
+ if (_isNuGetRepo || _isJFrogRepo || _isGHPkgsRepo || _isMyGetRepo || _isAWSCodeArtifactRepo)
{
return FindNameGlobbingFromNuGetRepo(packageName, tags, includePrerelease, out errRecord);
}
@@ -343,7 +364,7 @@ private FindResults FindNameGlobbingFromNuGetRepo(string packageName, string[] t
var names = packageName.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
string querySearchTerm;
- if (names.Length == 0)
+ if (names.Length == 0 && !_isAWSCodeArtifactRepo)
{
errRecord = new ErrorRecord(
new ArgumentException("-Name '*' for V3 server protocol repositories is not supported"),
@@ -834,7 +855,7 @@ private string[] GetVersionedPackageEntriesFromRegistrationsResource(string pack
///
/// Gets the versioned package entries from SearchQueryService resource
/// i.e when the package Name being searched for contains wildcards or a Tag query search is performed
- /// This is called by FindNameGlobbingFromNuGetRepo() and FindTagsFromNuGetRepo()
+ /// This is called by FindAll(), FindNameGlobbingFromNuGetRepo() and FindTagsFromNuGetRepo()
///
private List GetVersionedPackageEntriesFromSearchQueryResource(string queryTerm, bool includePrerelease, out ErrorRecord errRecord)
{
@@ -852,22 +873,27 @@ private List GetVersionedPackageEntriesFromSearchQueryResource(stri
return pkgEntries;
}
- // Get initial response
int skip = 0;
- string query = $"{searchQueryServiceUrl}?q={queryTerm}&prerelease={includePrerelease}&semVerLevel=2.0.0&skip={skip}&take=100";
+ int skipAndTakeAmount = 100;
+ if (_isAWSCodeArtifactRepo) {
+ skipAndTakeAmount = 25;
+ }
- // Get responses for all packages that contain the required tags
- pkgEntries.AddRange(GetJsonElementArr(query, dataName, out int initialCount, out errRecord).ToList());
+ // Get initial response
+ string query = $"{searchQueryServiceUrl}?q={queryTerm}&prerelease={includePrerelease}&semVerLevel=2.0.0&skip={skip}&take={skipAndTakeAmount}";
- // check count (ie "totalHits") 425 ==> count/100 ~~> 4 calls ~~> + 1 = 5 calls
- int count = initialCount / 100 + 1;
- // if more than 100 count, loop and add response to list
- while (count > 0)
- {
- skip += 100;
- query = $"{searchQueryServiceUrl}?q={queryTerm}&prerelease={includePrerelease}&semVerLevel=2.0.0&skip={skip}&take=100";
- pkgEntries.AddRange(GetJsonElementArr(query, dataName, out int unneededCount, out errRecord).ToList());
- count--;
+ var itemList = GetJsonElementArr(query, dataName, out int initialCount, out errRecord).ToList();
+ pkgEntries.AddRange(itemList);
+
+ // Get responses for all packages that contain the required tags
+ while (itemList.Count > 0) {
+ skip += skipAndTakeAmount;
+ query = $"{searchQueryServiceUrl}?q={queryTerm}&prerelease={includePrerelease}&semVerLevel=2.0.0&skip={skip}&take={skipAndTakeAmount}";
+ itemList = GetJsonElementArr(query, dataName, out int unneededCount, out errRecord).ToList();
+ if (itemList.Count == 0) {
+ break;
+ }
+ pkgEntries.AddRange(itemList);
}
return pkgEntries;
@@ -1716,6 +1742,14 @@ private static async Task SendV3RequestForContentAsync(HttpRequestM
}
}
+
+ ///
+ /// Helper method called by FindAll() to validate whether the repositories AbsoluteUri contains a specified value.
+ ///
+ private bool RepositoryUriContains(string str) {
+ return Repository.Uri.AbsoluteUri.ToLower().Contains(str);
+ }
+
#endregion
}
}
diff --git a/test/FindPSResourceTests/FindPSResourceV3Server.Tests.ps1 b/test/FindPSResourceTests/FindPSResourceV3Server.Tests.ps1
index dc1e46262..3dcdc1787 100644
--- a/test/FindPSResourceTests/FindPSResourceV3Server.Tests.ps1
+++ b/test/FindPSResourceTests/FindPSResourceV3Server.Tests.ps1
@@ -10,6 +10,8 @@ Write-Verbose -Verbose "Current module search paths: $psmodulePaths"
Describe 'Test HTTP Find-PSResource for V3 Server Protocol' -tags 'CI' {
BeforeAll{
+ $AWSCodeArtifactGalleryName = Get-AWSCodeArtifactGalleryName
+ $AWSCodeArtifactGalleryLocation = Get-AWSCodeArtifactGalleryLocation
$NuGetGalleryName = Get-NuGetGalleryName
$testModuleName = "test_module"
Get-NewPSResourceRepositoryFile
@@ -269,13 +271,23 @@ Describe 'Test HTTP Find-PSResource for V3 Server Protocol' -tags 'CI' {
$err[0].FullyQualifiedErrorId | Should -BeExactly "FindAllFailure,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource"
}
+ It "should support AWS CodeArtifact with find all resources given Name '*'" {
+ Register-PSResourceRepository -Name $AWSCodeArtifactGalleryName -Uri $AWSCodeArtifactGalleryLocation
+ $res = Find-PSResource -Name "*" -Repository $AWSCodeArtifactGalleryName -ErrorVariable err -ErrorAction SilentlyContinue
+ Unregister-PSResourceRepository -Name $AWSCodeArtifactGalleryName
+ $res | Should -BeNullOrEmpty
+ $err.Count | Should -BeGreaterThan 0
+ # The `HttpRequestCallFailure` error indicates the cmdlet moved past the fast-fail for `-Name '*'` not supported
+ $err[0].FullyQualifiedErrorId | Should -BeExactly "HttpRequestCallFailure,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource"
+ }
+
It "should not find an unlisted module" {
$res = Find-PSResource -Name "PMTestDependency1" -Repository $NuGetGalleryName -ErrorVariable err -ErrorAction SilentlyContinue
$res | Should -BeNullOrEmpty
$err.Count | Should -BeGreaterThan 0
$err[0].FullyQualifiedErrorId | Should -BeExactly "PackageNotFound,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource"
}
-
+
# "carb*" is intentionally chosen as a sequence that will trigger pagination (ie more than 100 results),
# but is not too time consuming.
# There are currently between 236 packages that should be returned
diff --git a/test/PSGetTestUtils.psm1 b/test/PSGetTestUtils.psm1
index c9f5006b4..dad8b6a15 100644
--- a/test/PSGetTestUtils.psm1
+++ b/test/PSGetTestUtils.psm1
@@ -22,6 +22,11 @@ $script:PSGalleryLocation = 'https://www.powershellgallery.com/api/v2'
$script:NuGetGalleryName = 'NuGetGallery'
$script:NuGetGalleryLocation = 'https://api.nuget.org/v3/index.json'
+# This is not a valid Code Artifact endpoint. However, this will allow a unit test to move
+# past the NuGet v3 fast fail in the FindAll() method.
+$script:AWSCodeArtifactName = 'AWSCodeArtifact'
+$script:AWSCodeArtifactLocation = 'https://cadomainname-awsaccountid.d.codeartifact.region.amazonaws.com/nuget/carepositoryname/v3/index.json'
+
if($script:IsInbox)
{
$script:ProgramFilesPSPath = Microsoft.PowerShell.Management\Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell"
@@ -135,6 +140,14 @@ function Get-PSGetLocalAppDataPath {
return $script:PSGetAppLocalPath
}
+function Get-AWSCodeArtifactGalleryName {
+ return $script:AWSCodeArtifactName
+}
+
+function Get-AWSCodeArtifactGalleryLocation {
+ return $script:AWSCodeArtifactLocation
+}
+
function Get-NuGetGalleryName
{
return $script:NuGetGalleryName