Skip to content

Commit 152e570

Browse files
authored
Install-PSResource -RequiredResource with empty inner hashtable value bugfix (#1426)
1 parent c554e24 commit 152e570

File tree

3 files changed

+72
-34
lines changed

3 files changed

+72
-34
lines changed

src/code/InstallPSResource.cs

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ private enum ResourceFileType
245245
private const string InputObjectParameterSet = "InputObjectParameterSet";
246246
private const string RequiredResourceFileParameterSet = "RequiredResourceFileParameterSet";
247247
private const string RequiredResourceParameterSet = "RequiredResourceParameterSet";
248+
private const string CredentialKey = "credential";
248249
List<string> _pathsToInstallPkg;
249250
private string _requiredResourceFile;
250251
private string _requiredResourceJson;
@@ -426,50 +427,76 @@ protected override void ProcessRecord()
426427
private void RequiredResourceHelper(Hashtable reqResourceHash)
427428
{
428429
WriteDebug("In InstallPSResource::RequiredResourceHelper()");
429-
var pkgNames = reqResourceHash.Keys;
430-
431-
foreach (string pkgName in pkgNames)
430+
foreach (DictionaryEntry entry in reqResourceHash)
432431
{
433-
var pkgParamInfo = reqResourceHash[pkgName];
432+
InstallPkgParams pkgParams = new InstallPkgParams();
433+
PSCredential pkgCredential = Credential;
434434

435-
// Format should now be a hashtable, whether the original input format was json or hashtable
436-
if (!(pkgParamInfo is Hashtable pkgInstallInfo))
435+
// The package name will be the key for the inner hashtable and is present for all scenarios,
436+
// including the scenario where only package name is specified
437+
// i.e Install-PSResource -RequiredResource @ { MyPackage = @{} }
438+
string pkgName = entry.Key.ToString();
439+
// check if pkgName is empty or whitespace
440+
if (String.IsNullOrEmpty(pkgName.Trim()))
437441
{
442+
var pkgNameEmptyOrWhitespaceError = new ErrorRecord(
443+
new ArgumentException($"The package name '{pkgName}' provided cannot be an empty string or whitespace."),
444+
"pkgNameEmptyOrWhitespaceError",
445+
ErrorCategory.InvalidArgument,
446+
this);
447+
448+
WriteError(pkgNameEmptyOrWhitespaceError);
438449
return;
439450
}
440451

441-
InstallPkgParams pkgParams = new InstallPkgParams();
442-
var pkgParamNames = pkgInstallInfo.Keys;
452+
string pkgVersion = String.Empty;
453+
if (!(entry.Value is Hashtable pkgInstallInfo))
454+
{
455+
var requiredResourceHashtableInputFormatError = new ErrorRecord(
456+
new ArgumentException($"The RequiredResource input with name '{pkgName}' does not have a valid value, the value must be a hashtable."),
457+
"RequiredResourceHashtableInputFormatError",
458+
ErrorCategory.InvalidArgument,
459+
this);
443460

444-
PSCredential pkgCredential = Credential;
445-
foreach (string paramName in pkgParamNames)
461+
WriteError(requiredResourceHashtableInputFormatError);
462+
return;
463+
}
464+
465+
// scenario where package name and other parameters are provided:
466+
// Install-PSResource -RequiredResource @ { MyPackage = @{ version = '1.2.3', repository = 'PSGallery' } }
467+
if (pkgInstallInfo.Count != 0)
446468
{
447-
if (string.Equals(paramName, "credential", StringComparison.InvariantCultureIgnoreCase))
448-
{
449-
WriteVerbose("Credential specified for required resource");
450-
pkgCredential = pkgInstallInfo[paramName] as PSCredential;
451-
}
469+
var pkgParamNames = pkgInstallInfo.Keys;
452470

453-
pkgParams.SetProperty(paramName, pkgInstallInfo[paramName] as string, out ErrorRecord IncorrectVersionFormat);
471+
foreach (string paramName in pkgParamNames)
472+
{
473+
if (string.Equals(paramName, CredentialKey, StringComparison.InvariantCultureIgnoreCase))
474+
{
475+
WriteVerbose("Credential specified for required resource");
476+
pkgCredential = pkgInstallInfo[paramName] as PSCredential;
477+
}
454478

455-
if (IncorrectVersionFormat != null)
479+
// for all parameters found, we try to add it to the InstallPkgParams object if it is valid.
480+
pkgParams.SetProperty(paramName, pkgInstallInfo[paramName] as string, out ErrorRecord ParameterParsingError);
481+
if (ParameterParsingError != null)
482+
{
483+
ThrowTerminatingError(ParameterParsingError);
484+
}
485+
}
486+
487+
if (pkgParams.Scope == ScopeType.AllUsers)
456488
{
457-
ThrowTerminatingError(IncorrectVersionFormat);
489+
_pathsToInstallPkg = Utils.GetAllInstallationPaths(this, pkgParams.Scope);
458490
}
459-
}
460-
461-
if (pkgParams.Scope == ScopeType.AllUsers)
462-
{
463-
_pathsToInstallPkg = Utils.GetAllInstallationPaths(this, pkgParams.Scope);
464-
}
465491

466-
string pkgVersion = pkgInstallInfo["version"] == null ? String.Empty : pkgInstallInfo["version"].ToString();
492+
pkgVersion = pkgInstallInfo["version"] == null ? String.Empty : pkgInstallInfo["version"].ToString();
493+
}
467494

468495
ProcessInstallHelper(
469496
pkgNames: new string[] { pkgName },
470497
pkgVersion: pkgVersion,
471498
pkgPrerelease: pkgParams.Prerelease,
472-
pkgRepository: new string[] { pkgParams.Repository },
499+
pkgRepository: pkgParams.Repository != null ? new string[] { pkgParams.Repository } : new string[]{},
473500
pkgCredential: pkgCredential,
474501
reqResourceParams: pkgParams);
475502
}

src/code/InstallPkgParams.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,18 @@ public class InstallPkgParams
2525

2626
#region Private methods
2727

28-
public void SetProperty(string propertyName, string propertyValue, out ErrorRecord IncorrectVersionFormat)
28+
public void SetProperty(string propertyName, string propertyValue, out ErrorRecord ParameterParsingError)
2929
{
30-
IncorrectVersionFormat = null;
30+
ParameterParsingError = null;
31+
if (String.IsNullOrEmpty(propertyName.Trim()))
32+
{
33+
ParameterParsingError = new ErrorRecord(
34+
new ArgumentException("Argument for parameter cannot be null or whitespace."),
35+
"EmptyOrWhitespaceParameterKey",
36+
ErrorCategory.InvalidArgument,
37+
this);
38+
}
39+
3140
switch (propertyName.ToLower())
3241
{
3342
case "name":
@@ -44,7 +53,7 @@ public void SetProperty(string propertyName, string propertyValue, out ErrorReco
4453
}
4554
else if (!Utils.TryParseVersionOrVersionRange(propertyValue, out versionTmp))
4655
{
47-
IncorrectVersionFormat = new ErrorRecord(
56+
ParameterParsingError = new ErrorRecord(
4857
new ArgumentException("Argument for Version parameter is not in the proper format."),
4958
"IncorrectVersionFormat",
5059
ErrorCategory.InvalidArgument,
@@ -98,7 +107,11 @@ public void SetProperty(string propertyName, string propertyValue, out ErrorReco
98107
break;
99108

100109
default:
101-
// write error
110+
ParameterParsingError = new ErrorRecord(
111+
new ArgumentException($"The parameter '{propertyName}' provided is not a recognized or valid parameter. Allowed values include: Name, Version, Repository, AcceptLicense, Prerelease, Scope, Quiet, Reinstall, TrustRepository, NoClobber, and SkipDependencyCheck."),
112+
"IncorrectParameterError",
113+
ErrorCategory.InvalidArgument,
114+
this);
102115
break;
103116
}
104117
}

test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,13 @@ Describe 'Test Install-PSResource for V2 Server scenarios' -tags 'CI' {
389389
repository = $PSGalleryName
390390
}
391391

392-
test_module2 = @{
392+
test_module2 = @{
393393
version = "[1.0.0,3.0.0)"
394394
repository = $PSGalleryName
395395
prerelease = "true"
396396
}
397397

398-
TestModule99 = @{
399-
repository = $PSGalleryName
400-
}
398+
TestModule99 = @{}
401399
}
402400

403401
Install-PSResource -RequiredResource $rrHash -TrustRepository

0 commit comments

Comments
 (0)