Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/code/ContainerRegistryServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ internal class ContainerRegistryServerAPICalls : ServerApiCall
#region Members

public override PSRepositoryInfo Repository { get; set; }
internal override bool WriteWarnings { get; set; }
public String Registry { get; set; }
private readonly PSCmdlet _cmdletPassedIn;
private HttpClient _sessionClient { get; set; }
Expand Down
6 changes: 4 additions & 2 deletions src/code/FindHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,10 @@ public IEnumerable<PSResourceInfo> FindByResourceName(
// Set network credentials via passed in credentials, AzArtifacts CredentialProvider, or SecretManagement.
_networkCredential = currentRepository.SetNetworkCredentials(_networkCredential, _cmdletPassedIn);

ServerApiCall currentServer = ServerFactory.GetServer(currentRepository, _cmdletPassedIn, _networkCredential);
bool shouldReportErrorForEachRepo = !suppressErrors && !_repositoryNameContainsWildcard;
bool shouldWriteWarningsForRepo = !shouldReportErrorForEachRepo; // Only write warnings for a repository if we are not writing errors for each repository.

ServerApiCall currentServer = ServerFactory.GetServer(currentRepository, _cmdletPassedIn, _networkCredential, writeWarnings: shouldWriteWarningsForRepo);
if (currentServer == null)
{
// this indicates that PSRepositoryInfo.APIVersion = PSRepositoryInfo.APIVersion.unknown
Expand All @@ -222,7 +225,6 @@ public IEnumerable<PSResourceInfo> FindByResourceName(
ResponseUtil currentResponseUtil = ResponseUtilFactory.GetResponseUtil(currentRepository);
_cmdletPassedIn.WriteDebug($"Searching through repository '{currentRepository.Name}'");

bool shouldReportErrorForEachRepo = !suppressErrors && !_repositoryNameContainsWildcard;
foreach (PSResourceInfo currentPkg in SearchByNames(currentServer, currentResponseUtil, currentRepository, shouldReportErrorForEachRepo))
{
if (currentPkg == null)
Expand Down
11 changes: 8 additions & 3 deletions src/code/InstallHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ private List<PSResourceInfo> ProcessRepositories(
{
_cmdletPassedIn.WriteDebug("In InstallHelper::ProcessRepositories()");
List<PSResourceInfo> allPkgsInstalled = new();
bool containsWildcard = false;
if (repository != null && repository.Length != 0)
{
// Write error and disregard repository entries containing wildcards.
Expand All @@ -199,7 +200,6 @@ private List<PSResourceInfo> ProcessRepositories(

// If repository entries includes wildcards and non-wildcard names, write terminating error
// Ex: -Repository *Gallery, localRepo
bool containsWildcard = false;
bool containsNonWildcard = false;
foreach (string repoName in repository)
{
Expand All @@ -222,6 +222,10 @@ private List<PSResourceInfo> ProcessRepositories(
_cmdletPassedIn));
}
}
else
{
containsWildcard = true;
}

// Get repositories to search.
List<PSRepositoryInfo> repositoriesToSearch;
Expand Down Expand Up @@ -289,7 +293,8 @@ private List<PSResourceInfo> ProcessRepositories(
// Set network credentials via passed in credentials, AzArtifacts CredentialProvider, or SecretManagement.
_networkCredential = currentRepository.SetNetworkCredentials(_networkCredential, _cmdletPassedIn);

ServerApiCall currentServer = ServerFactory.GetServer(currentRepository, _cmdletPassedIn, _networkCredential);
bool writeWarningsForRepo = containsWildcard;
ServerApiCall currentServer = ServerFactory.GetServer(currentRepository, _cmdletPassedIn, _networkCredential, writeWarningsForRepo);

if (currentServer == null)
{
Expand Down Expand Up @@ -537,7 +542,7 @@ private List<PSResourceInfo> InstallPackages(
errRecord: out ErrorRecord errRecord);

// At this point parent package is installed to temp path.
if (errRecord != null)
if (errRecord != null && !currentServer.WriteWarnings)
{
if (errRecord.FullyQualifiedErrorId.Equals("PackageNotFound"))
{
Expand Down
144 changes: 134 additions & 10 deletions src/code/LocalServerApiCalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ internal class LocalServerAPICalls : ServerApiCall
private readonly PSCmdlet _cmdletPassedIn;
private readonly FindResponseType _localServerFindResponseType = FindResponseType.ResponseHashtable;
private readonly string _fileTypeKey = "filetype";
internal override bool WriteWarnings { get; set; }

#endregion

#region Constructor

public LocalServerAPICalls (PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, NetworkCredential networkCredential) : base (repository, networkCredential)
public LocalServerAPICalls (PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, NetworkCredential networkCredential, bool writeWarnings = false) : base (repository, networkCredential, writeWarnings)
{
this.Repository = repository;
this.WriteWarnings = writeWarnings;
_cmdletPassedIn = cmdletPassedIn;
}

Expand Down Expand Up @@ -263,7 +265,28 @@ private FindResults FindNameHelper(string packageName, string[] tags, bool inclu
string regexPattern = $"{packageName}" + @"(\.\d+){1,3}(?:[a-zA-Z0-9-.]+|.\d)?\.nupkg";
_cmdletPassedIn.WriteDebug($"package file name pattern to be searched for is: {regexPattern}");

foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
string[] foundFiles = Utils.EmptyStrArray;
try
{
foundFiles = Directory.GetFiles(Repository.Uri.LocalPath);
}
catch (Exception e)
{
if (WriteWarnings)
{
_cmdletPassedIn.WriteWarning($"Unable to resolve repository '{Repository.Name}' with source '{Repository.Uri.LocalPath}' due to exception: {e.Message}");
}

errRecord = new ErrorRecord(
exception: e,
"FileAccessFailure",
ErrorCategory.ReadError,
this);

return findResponse;
}

foreach (string path in foundFiles)
{
string packageFullName = Path.GetFileName(path);
bool isMatch = Regex.IsMatch(packageFullName, regexPattern, RegexOptions.IgnoreCase);
Expand Down Expand Up @@ -333,7 +356,12 @@ private FindResults FindNameGlobbingHelper(string packageName, string[] tags, bo
List<Hashtable> pkgsFound = new List<Hashtable>();
errRecord = null;

Hashtable pkgVersionsFound = GetMatchingFilesGivenNamePattern(packageNameWithWildcard: packageName, includePrerelease: includePrerelease);
Hashtable pkgVersionsFound = GetMatchingFilesGivenNamePattern(packageNameWithWildcard: packageName, includePrerelease: includePrerelease, out errRecord);
if (errRecord != null)
{
// ErrorRecord errRecord is only set if directory access to retrieve files failed (i.e network error when accessing file share, incorrect directory path, etc), not if desired files within directory are not found since this is a wildcard scenario.
return findResponse;
}

List<string> pkgNamesList = pkgVersionsFound.Keys.Cast<string>().ToList();
foreach(string pkgFound in pkgNamesList)
Expand Down Expand Up @@ -382,7 +410,28 @@ private FindResults FindVersionHelper(string packageName, string version, string
string pkgPath = String.Empty;
string actualPkgName = String.Empty;

foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
string[] foundFiles = Utils.EmptyStrArray;
try
{
foundFiles = Directory.GetFiles(Repository.Uri.LocalPath);
}
catch (Exception e)
{
if (WriteWarnings)
{
_cmdletPassedIn.WriteWarning($"Unable to resolve repository '{Repository.Name}' with source '{Repository.Uri.LocalPath}' due to exception: {e.Message}");
}

errRecord = new ErrorRecord(
exception: e,
"FileAccessFailure",
ErrorCategory.ReadError,
this);

return findResponse;
}

foreach (string path in foundFiles)
{
string packageFullName = Path.GetFileName(path);
bool isMatch = Regex.IsMatch(packageFullName, regexPattern, RegexOptions.IgnoreCase);
Expand Down Expand Up @@ -450,7 +499,12 @@ private FindResults FindTagsHelper(string[] tags, bool includePrerelease, out Er
List<Hashtable> pkgsFound = new List<Hashtable>();
errRecord = null;

Hashtable pkgVersionsFound = GetMatchingFilesGivenNamePattern(packageNameWithWildcard: String.Empty, includePrerelease: includePrerelease);
Hashtable pkgVersionsFound = GetMatchingFilesGivenNamePattern(packageNameWithWildcard: String.Empty, includePrerelease: includePrerelease, errRecord: out errRecord);
if (errRecord != null)
{
// ErrorRecord errRecord is only set if directory access to retrieve files failed (i.e network error when accessing file share, incorrect directory path, etc), not if desired files within directory are not found since this is a wildcard scenario.
return findResponse;
}

List<string> pkgNamesList = pkgVersionsFound.Keys.Cast<string>().ToList();
foreach(string pkgFound in pkgNamesList)
Expand Down Expand Up @@ -496,7 +550,23 @@ private Stream InstallName(string packageName, bool includePrerelease, out Error
NuGetVersion latestVersion = new NuGetVersion("0.0.0.0");
String latestVersionPath = String.Empty;

foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
string[] foundFiles = Utils.EmptyStrArray;
try
{
foundFiles = Directory.GetFiles(Repository.Uri.LocalPath);
}
catch (Exception e)
{
errRecord = new ErrorRecord(
exception: e,
"FileAccessFailure",
ErrorCategory.ReadError,
this);

return fs;
}

foreach (string path in foundFiles)
{
string packageFullName = Path.GetFileName(path);

Expand Down Expand Up @@ -581,7 +651,28 @@ private Stream InstallVersion(string packageName, string version, out ErrorRecor
WildcardPattern pkgNamePattern = new WildcardPattern($"{packageName}.{version}.nupkg*", WildcardOptions.IgnoreCase);
String pkgVersionPath = String.Empty;

foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
string[] foundFiles = Utils.EmptyStrArray;
try
{
foundFiles = Directory.GetFiles(Repository.Uri.LocalPath);
}
catch (Exception e)
{
if (WriteWarnings)
{
_cmdletPassedIn.WriteWarning($"Unable to resolve repository '{Repository.Name}' with source '{Repository.Uri.LocalPath}' due to exception: {e.Message}");
}

errRecord = new ErrorRecord(
exception: e,
"FileAccessFailure",
ErrorCategory.ReadError,
this);

return fs;
}

foreach (string path in foundFiles)
{
string packageFullName = Path.GetFileName(path);

Expand Down Expand Up @@ -778,7 +869,23 @@ private Hashtable GetMatchingFilesGivenSpecificName(string packageName, bool inc
Hashtable pkgVersionsFound = new Hashtable(StringComparer.OrdinalIgnoreCase);
errRecord = null;

foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
string[] foundFiles = Utils.EmptyStrArray;
try
{
foundFiles = Directory.GetFiles(Repository.Uri.LocalPath);
}
catch (Exception e)
{
errRecord = new ErrorRecord(
exception: e,
"FileAccessFailure",
ErrorCategory.ReadError,
this);

return pkgVersionsFound;
}

foreach (string path in foundFiles)
{
string packageFullName = Path.GetFileName(path);

Expand Down Expand Up @@ -809,9 +916,10 @@ private Hashtable GetMatchingFilesGivenSpecificName(string packageName, bool inc
/// hashtable with those that match the name wildcard pattern and prerelease requirements provided.
/// This helper method is called for FindAll(), FindTags(), FindNameGlobbing() scenarios.
/// </summary>
private Hashtable GetMatchingFilesGivenNamePattern(string packageNameWithWildcard, bool includePrerelease)
private Hashtable GetMatchingFilesGivenNamePattern(string packageNameWithWildcard, bool includePrerelease, out ErrorRecord errRecord)
{
_cmdletPassedIn.WriteDebug("In LocalServerApiCalls::GetMatchingFilesGivenNamePattern()");
errRecord = null;
bool isNameFilteringRequired = !String.IsNullOrEmpty(packageNameWithWildcard);

// wildcard name possibilities: power*, *get, power*get
Expand All @@ -820,7 +928,23 @@ private Hashtable GetMatchingFilesGivenNamePattern(string packageNameWithWildcar
Regex rx = new Regex(@"\.\d+\.", RegexOptions.Compiled | RegexOptions.IgnoreCase);
Hashtable pkgVersionsFound = new Hashtable(StringComparer.OrdinalIgnoreCase);

foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
string[] foundFiles = Utils.EmptyStrArray;
try
{
foundFiles = Directory.GetFiles(Repository.Uri.LocalPath);
}
catch (Exception e)
{
errRecord = new ErrorRecord(
exception: e,
"FileAccessFailure",
ErrorCategory.ReadError,
this);

return pkgVersionsFound;
}

foreach (string path in foundFiles)
{
string packageFullName = Path.GetFileName(path);
MatchCollection matches = rx.Matches(packageFullName);
Expand Down
1 change: 1 addition & 0 deletions src/code/NuGetServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal class NuGetServerAPICalls : ServerApiCall
#region Members

public override PSRepositoryInfo Repository { get; set; }
internal override bool WriteWarnings { get; set; }
private readonly PSCmdlet _cmdletPassedIn;
private HttpClient _sessionClient { get; set; }
private static readonly Hashtable[] emptyHashResponses = new Hashtable[]{};
Expand Down
8 changes: 8 additions & 0 deletions src/code/ServerApiCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,20 @@ internal abstract class ServerApiCall : IServerAPICalls
#region Members

public abstract PSRepositoryInfo Repository { get; set; }
internal abstract bool WriteWarnings { get; set; }
private HttpClient _sessionClient { get; set; }

#endregion

#region Constructor

public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCredential, bool writeWarnings)
: this(repository, networkCredential)
{
this.WriteWarnings = writeWarnings;
}


public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCredential)
{
this.Repository = repository;
Expand Down
4 changes: 2 additions & 2 deletions src/code/ServerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ internal static string UserAgentString()

internal class ServerFactory
{
public static ServerApiCall GetServer(PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, NetworkCredential networkCredential)
public static ServerApiCall GetServer(PSRepositoryInfo repository, PSCmdlet cmdletPassedIn, NetworkCredential networkCredential, bool writeWarnings = false)
{
PSRepositoryInfo.APIVersion repoApiVersion = repository.ApiVersion;
ServerApiCall currentServer = null;
Expand All @@ -47,7 +47,7 @@ public static ServerApiCall GetServer(PSRepositoryInfo repository, PSCmdlet cmdl
break;

case PSRepositoryInfo.APIVersion.Local:
currentServer = new LocalServerAPICalls(repository, cmdletPassedIn, networkCredential);
currentServer = new LocalServerAPICalls(repository, cmdletPassedIn, networkCredential, writeWarnings);
break;

case PSRepositoryInfo.APIVersion.NugetServer:
Expand Down
1 change: 1 addition & 0 deletions src/code/V2ServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ internal class V2ServerAPICalls : ServerApiCall
#region Members

public override PSRepositoryInfo Repository { get; set; }
internal override bool WriteWarnings { get; set; }
private readonly PSCmdlet _cmdletPassedIn;
private HttpClient _sessionClient { get; set; }
private static readonly Hashtable[] emptyHashResponses = new Hashtable[]{};
Expand Down
1 change: 1 addition & 0 deletions src/code/V3ServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal class V3ServerAPICalls : ServerApiCall
{
#region Members
public override PSRepositoryInfo Repository { get; set; }
internal override bool WriteWarnings { get; set; }
private readonly PSCmdlet _cmdletPassedIn;
private HttpClient _sessionClient { get; set; }
private bool _isNuGetRepo { get; set; }
Expand Down
19 changes: 19 additions & 0 deletions test/FindPSResourceTests/FindPSResourceLocal.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' {
BeforeAll{
$localRepo = "psgettestlocal"
$localUNCRepo = 'psgettestlocal3'
$localPrivateRepo = "psgettestlocal5"
$testModuleName = "test_local_mod"
$testModuleName2 = "test_local_mod2"
$testModuleName3 = "Test_Local_Mod3"
Expand Down Expand Up @@ -347,4 +348,22 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' {
$res = Find-PSResource -Name 'Az.KeyVault' -Repository $localRepo
$res.Version | Should -Be "6.3.1"
}

It "Find should not silently fail if network connection to local private repository cannot be established and remainder repositories should be searched" {
$privateRepo = Get-PSResourceRepository $localPrivateRepo
$res = Find-PSResource -Name $testModuleName -WarningVariable WarningVar -WarningAction SilentlyContinue
$WarningVar | Should -Not -BeNullOrEmpty
$WarningVar[0] | Should -Match "*$($privateRepo.Uri.LocalPath)*"
$res.Name | Should -Contain $testModuleName
$res.Version | Should -Be "1.0.0"
}

It "Find should not silently fail if network connection to local private repository cannot be established and package version was provided and remainder repositories should be searched" {
$privateRepo = Get-PSResourceRepository $localPrivateRepo
$res = Find-PSResource -Name $testModuleName -Version "1.0.0" -WarningVariable WarningVar -WarningAction SilentlyContinue
$WarningVar | Should -Not -BeNullOrEmpty
$WarningVar[0] | Should -Match "*$($privateRepo.Uri.LocalPath)*"
$res.Name | Should -Contain $testModuleName
$res.Version | Should -Be "1.0.0"
}
}
Loading
Loading