Skip to content

Commit e160b6f

Browse files
authored
Implement unimplemented concurrency methods for all server classes (#2012)
1 parent 6ecc668 commit e160b6f

7 files changed

Lines changed: 687 additions & 186 deletions

src/code/ContainerRegistryServerAPICalls.cs

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,40 @@ public ContainerRegistryServerAPICalls(PSRepositoryInfo repository, PSCmdlet cmd
8282

8383
#region Overridden Methods
8484

85+
/// <summary>
86+
/// Async find method which allows for searching for single name with specific version.
87+
/// Name: no wildcard support
88+
/// Version: no wildcard support
89+
/// This is the concurrent (parallel) counterpart of FindVersion().
90+
/// </summary>
8591
public override Task<FindResults> FindVersionAsync(string packageName, string version, ResourceType type, ConcurrentQueue<ErrorRecord> errorMsgs, ConcurrentQueue<string> warningMsgs, ConcurrentQueue<string> debugMsgs, ConcurrentQueue<string> verboseMsgs)
8692
{
87-
throw new NotImplementedException("FindVersionAsync is not implemented for ContainerRegistryServerAPICalls.");
93+
debugMsgs.Enqueue("In ContainerRegistryServerAPICalls::FindVersionAsync()");
94+
FindResults findResponse = FindVersion(packageName, version, type, out ErrorRecord errRecord);
95+
if (errRecord != null)
96+
{
97+
errorMsgs.Enqueue(errRecord);
98+
}
99+
100+
return Task.FromResult(findResponse);
88101
}
89102

103+
/// <summary>
104+
/// Async find method which allows for searching for single name with version range.
105+
/// Name: no wildcard support
106+
/// Version: supports wildcards
107+
/// This is the concurrent (parallel) counterpart of FindVersionGlobbing().
108+
/// </summary>
90109
public override Task<FindResults> FindVersionGlobbingAsync(string packageName, VersionRange versionRange, bool includePrerelease, ResourceType type, bool getOnlyLatest, ConcurrentQueue<ErrorRecord> errorMsgs, ConcurrentQueue<string> warningMsgs, ConcurrentQueue<string> debugMsgs, ConcurrentQueue<string> verboseMsgs)
91110
{
92-
throw new NotImplementedException("FindVersionGlobbingAsync is not implemented for ContainerRegistryServerAPICalls.");
111+
debugMsgs.Enqueue("In ContainerRegistryServerAPICalls::FindVersionGlobbingAsync()");
112+
FindResults findResponse = FindVersionGlobbing(packageName, versionRange, includePrerelease, type, getOnlyLatest, out ErrorRecord errRecord);
113+
if (errRecord != null)
114+
{
115+
errorMsgs.Enqueue(errRecord);
116+
}
117+
118+
return Task.FromResult(findResponse);
93119
}
94120

95121
/// <summary>
@@ -158,9 +184,21 @@ public override FindResults FindName(string packageName, bool includePrerelease,
158184
}
159185

160186

187+
/// <summary>
188+
/// Async find method which allows for searching for single name and returns latest version.
189+
/// Name: no wildcard support
190+
/// This is the concurrent (parallel) counterpart of FindName().
191+
/// </summary>
161192
public override Task<FindResults> FindNameAsync(string packageName, bool includePrerelease, ResourceType type, ConcurrentQueue<ErrorRecord> errorMsgs, ConcurrentQueue<string> warningMsgs, ConcurrentQueue<string> debugMsgs, ConcurrentQueue<string> verboseMsgs)
162193
{
163-
throw new NotImplementedException("FindNameAsync is not implemented for ContainerRegistryServerAPICalls.");
194+
debugMsgs.Enqueue("In ContainerRegistryServerAPICalls::FindNameAsync()");
195+
FindResults findResponse = FindName(packageName, includePrerelease, type, out ErrorRecord errRecord);
196+
if (errRecord != null)
197+
{
198+
errorMsgs.Enqueue(errRecord);
199+
}
200+
201+
return Task.FromResult(findResponse);
164202
}
165203

166204
/// <summary>
@@ -329,7 +367,22 @@ public override Stream InstallPackage(string packageName, string packageVersion,
329367
/// </summary>
330368
public override Task<Stream> InstallPackageAsync(string packageName, string packageVersion, bool includePrerelease, ConcurrentQueue<ErrorRecord> errorMsgs, ConcurrentQueue<string> warningMsgs, ConcurrentQueue<string> debugMsgs, ConcurrentQueue<string> verboseMsgs)
331369
{
332-
throw new NotImplementedException("FindNameAsync is not implemented for ContainerRegistryServerAPICalls.");
370+
debugMsgs.Enqueue("In ContainerRegistryServerAPICalls::InstallPackageAsync()");
371+
Stream results = new MemoryStream();
372+
if (string.IsNullOrEmpty(packageVersion))
373+
{
374+
errorMsgs.Enqueue(new ErrorRecord(
375+
exception: new ArgumentNullException($"Package version could not be found for {packageName}"),
376+
"PackageVersionNullOrEmptyError",
377+
ErrorCategory.InvalidArgument,
378+
_cmdletPassedIn));
379+
380+
return Task.FromResult(results);
381+
}
382+
383+
string packageNameForInstall = PrependMARPrefix(packageName);
384+
results = InstallVersionAsync(packageNameForInstall, packageVersion, errorMsgs, debugMsgs, verboseMsgs);
385+
return Task.FromResult(results);
333386
}
334387

335388
/// <summary>
@@ -400,6 +453,76 @@ private Stream InstallVersion(
400453
return responseContent.ReadAsStreamAsync().Result;
401454
}
402455

456+
/// <summary>
457+
/// Installs a package with version specified using concurrent queues for output instead of cmdlet streams.
458+
/// Used by the async install path to avoid cross-thread cmdlet stream writes.
459+
/// </summary>
460+
private Stream InstallVersionAsync(
461+
string packageName,
462+
string packageVersion,
463+
ConcurrentQueue<ErrorRecord> errorMsgs,
464+
ConcurrentQueue<string> debugMsgs,
465+
ConcurrentQueue<string> verboseMsgs)
466+
{
467+
debugMsgs.Enqueue("In ContainerRegistryServerAPICalls::InstallVersionAsync()");
468+
string packageNameLowercase = packageName.ToLower();
469+
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
470+
try
471+
{
472+
Directory.CreateDirectory(tempPath);
473+
}
474+
catch (Exception e)
475+
{
476+
errorMsgs.Enqueue(new ErrorRecord(
477+
exception: e,
478+
"InstallVersionTempDirCreationError",
479+
ErrorCategory.InvalidResult,
480+
_cmdletPassedIn));
481+
482+
return null;
483+
}
484+
485+
string containerRegistryAccessToken = GetContainerRegistryAccessToken(needCatalogAccess: false, isPushOperation: false, out ErrorRecord errRecord);
486+
if (errRecord != null)
487+
{
488+
errorMsgs.Enqueue(errRecord);
489+
return null;
490+
}
491+
492+
verboseMsgs.Enqueue($"Getting manifest for {packageNameLowercase} - {packageVersion}");
493+
var manifest = GetContainerRegistryRepositoryManifest(packageNameLowercase, packageVersion, containerRegistryAccessToken, out errRecord);
494+
if (errRecord != null)
495+
{
496+
errorMsgs.Enqueue(errRecord);
497+
return null;
498+
}
499+
string digest = GetDigestFromManifest(manifest, out errRecord);
500+
if (errRecord != null)
501+
{
502+
errorMsgs.Enqueue(errRecord);
503+
return null;
504+
}
505+
506+
verboseMsgs.Enqueue($"Downloading blob for {packageNameLowercase} - {packageVersion}");
507+
HttpContent responseContent;
508+
try
509+
{
510+
responseContent = GetContainerRegistryBlobAsync(packageNameLowercase, digest, containerRegistryAccessToken).Result;
511+
}
512+
catch (Exception e)
513+
{
514+
errorMsgs.Enqueue(new ErrorRecord(
515+
exception: e,
516+
"InstallVersionGetContainerRegistryBlobAsyncError",
517+
ErrorCategory.InvalidResult,
518+
_cmdletPassedIn));
519+
520+
return null;
521+
}
522+
523+
return responseContent.ReadAsStreamAsync().Result;
524+
}
525+
403526
#endregion
404527

405528
#region Authentication and Token Methods

0 commit comments

Comments
 (0)