Skip to content

Add InputObject parameter sets for appropriate *-PSResource cmdlets, to provide pipeline support #510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Oct 18, 2021
Merged
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
169 changes: 102 additions & 67 deletions src/code/InstallPSResource.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Collections.Specialized;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
Expand Down Expand Up @@ -26,14 +25,14 @@ class InstallPSResource : PSCmdlet
/// Specifies the exact names of resources to install from a repository.
/// A comma-separated list of module names is accepted. The resource name must match the resource name in the repository.
/// </summary>
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true, ParameterSetName = NameParameterSet)]
[Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true, ParameterSetName = NameParameterSet)]
[ValidateNotNullOrEmpty]
public string[] Name { get; set; }

/// <summary>
/// Specifies the version or version range of the package to be installed
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = NameParameterSet)]
[ValidateNotNullOrEmpty]
public string Version { get; set; }

Expand All @@ -54,44 +53,58 @@ class InstallPSResource : PSCmdlet
/// <summary>
/// Specifies a user account that has rights to find a resource from a specific repository.
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = InputObjectParameterSet)]
public PSCredential Credential { get; set; }

/// <summary>
/// Specifies the scope of installation.
/// </summary>
[Parameter(ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = InputObjectParameterSet)]
public ScopeType Scope { get; set; }

/// <summary>
/// Suppresses being prompted for untrusted sources.
/// </summary>
[Parameter(ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = InputObjectParameterSet)]
public SwitchParameter TrustRepository { get; set; }

/// <summary>
/// Overwrites a previously installed resource with the same name and version.
/// </summary>
[Parameter(ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = InputObjectParameterSet)]
public SwitchParameter Reinstall { get; set; }

/// <summary>
/// Suppresses progress information.
/// </summary>
[Parameter(ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = InputObjectParameterSet)]
public SwitchParameter Quiet { get; set; }

/// <summary>
/// For modules that require a license, AcceptLicense automatically accepts the license agreement during installation.
/// </summary>
[Parameter(ParameterSetName = NameParameterSet)]
[Parameter(ParameterSetName = InputObjectParameterSet)]
public SwitchParameter AcceptLicense { get; set; }

/// <summary>
/// Used for pipeline input.
/// </summary>
[Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true, ParameterSetName = InputObjectParameterSet)]
[ValidateNotNullOrEmpty]
public PSResourceInfo InputObject { get; set; }

#endregion

#region Members

private const string NameParameterSet = "NameParameterSet";
private const string InputObjectParameterSet = "InputObjectParameterSet";
private const string RequiredResourceFileParameterSet = "RequiredResourceFileParameterSet";
private const string RequiredResourceParameterSet = "RequiredResourceParameterSet";
List<string> _pathsToInstallPkg;
Expand All @@ -107,87 +120,51 @@ protected override void BeginProcessing()
// This is to create a better experience for those who have just installed v3 and want to get up and running quickly
RepositorySettings.CheckRepositoryStore();

// validate that if a -Version param is passed in that it can be parsed into a NuGet version range.
// An exact version will be formatted into a version range.
if (ParameterSetName.Equals(NameParameterSet) && Version != null && !Utils.TryParseVersionOrVersionRange(Version, out _versionRange))

{
var exMessage = "Argument for -Version parameter is not in the proper format.";
var ex = new ArgumentException(exMessage);
var IncorrectVersionFormat = new ErrorRecord(ex, "IncorrectVersionFormat", ErrorCategory.InvalidArgument, null);
ThrowTerminatingError(IncorrectVersionFormat);
}

// if no Version specified, install latest version for the package
if (Version == null)
{
_versionRange = VersionRange.All;
}

_pathsToInstallPkg = Utils.GetAllInstallationPaths(this, Scope);
}

protected override void ProcessRecord()
{
if (!ShouldProcess(string.Format("package to install: '{0}'", String.Join(", ", Name))))
{
WriteVerbose(string.Format("Install operation cancelled by user for packages: {0}", String.Join(", ", Name)));
return;
}

var installHelper = new InstallHelper(updatePkg: false, savePkg: false, cmdletPassedIn: this);

switch (ParameterSetName)
{
case NameParameterSet:
var namesToInstall = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard);
if (nameContainsWildcard)
// If no Version specified, install latest version for the package.
// Otherwise validate Version can be parsed out successfully.
if (Version == null)
{
WriteError(new ErrorRecord(
new PSInvalidOperationException("Name with wildcards is not supported for Install-PSResource cmdlet"),
"NameContainsWildcard",
ErrorCategory.InvalidArgument,
this));
return;
_versionRange = VersionRange.All;
}

foreach (string error in errorMsgs)
else if (!Utils.TryParseVersionOrVersionRange(Version, out _versionRange))
{
WriteError(new ErrorRecord(
new PSInvalidOperationException(error),
"ErrorFilteringNamesForUnsupportedWildcards",
ErrorCategory.InvalidArgument,
this));
var exMessage = "Argument for -Version parameter is not in the proper format.";
var ex = new ArgumentException(exMessage);
var IncorrectVersionFormat = new ErrorRecord(ex, "IncorrectVersionFormat", ErrorCategory.InvalidArgument, null);
ThrowTerminatingError(IncorrectVersionFormat);
}

// this catches the case where Name wasn't passed in as null or empty,
// but after filtering out unsupported wildcard names there are no elements left in namesToInstall
if (namesToInstall.Length == 0)
ProcessInstallHelper(installHelper: installHelper,
pkgNames: Name,
pkgPrerelease: Prerelease,
pkgRepository: Repository);
break;

case InputObjectParameterSet:
string normalizedVersionString = Utils.GetNormalizedVersionString(InputObject.Version.ToString(), InputObject.PrereleaseLabel);
if (!Utils.TryParseVersionOrVersionRange(normalizedVersionString, out _versionRange))
{
return;
var exMessage = String.Format("Version '{0}' for resource '{1}' cannot be parsed.", normalizedVersionString, InputObject.Name);
var ex = new ArgumentException(exMessage);
var ErrorParsingVersion = new ErrorRecord(ex, "ErrorParsingVersion", ErrorCategory.ParserError, null);
WriteError(ErrorParsingVersion);
}

installHelper.InstallPackages(
names: namesToInstall,
versionRange: _versionRange,
prerelease: Prerelease,
repository: Repository,
acceptLicense: AcceptLicense,
quiet: Quiet,
reinstall: Reinstall,
force: false,
trustRepository: TrustRepository,
noClobber: false,
credential: Credential,
requiredResourceFile: null,
requiredResourceJson: null,
requiredResourceHash: null,
specifiedPath: null,
asNupkg: false,
includeXML: true,
pathsToInstallPkg: _pathsToInstallPkg);
ProcessInstallHelper(installHelper: installHelper,
pkgNames: new string[] { InputObject.Name },
pkgPrerelease: InputObject.IsPrerelease,
pkgRepository: new string[]{ InputObject.Repository });
break;

case RequiredResourceFileParameterSet:
ThrowTerminatingError(new ErrorRecord(
new PSNotImplementedException("RequiredResourceFileParameterSet is not yet implemented. Please rerun cmdlet with other parameter set."),
Expand All @@ -211,5 +188,63 @@ protected override void ProcessRecord()
}

#endregion

#region Methods
private void ProcessInstallHelper(InstallHelper installHelper, string[] pkgNames, bool pkgPrerelease, string[] pkgRepository)
{
var inputNameToInstall = Utils.ProcessNameWildcards(pkgNames, out string[] errorMsgs, out bool nameContainsWildcard);
if (nameContainsWildcard)
{
WriteError(new ErrorRecord(
new PSInvalidOperationException("Name with wildcards is not supported for Install-PSResource cmdlet"),
"NameContainsWildcard",
ErrorCategory.InvalidArgument,
this));
return;
}

foreach (string error in errorMsgs)
{
WriteError(new ErrorRecord(
new PSInvalidOperationException(error),
"ErrorFilteringNamesForUnsupportedWildcards",
ErrorCategory.InvalidArgument,
this));
}

// this catches the case where Name wasn't passed in as null or empty,
// but after filtering out unsupported wildcard names there are no elements left in namesToInstall
if (inputNameToInstall.Length == 0)
{
return;
}

if (!ShouldProcess(string.Format("package to install: '{0}'", String.Join(", ", inputNameToInstall))))
{
WriteVerbose(string.Format("Install operation cancelled by user for packages: {0}", String.Join(", ", inputNameToInstall)));
return;
}

installHelper.InstallPackages(
names: pkgNames,
versionRange: _versionRange,
prerelease: pkgPrerelease,
repository: pkgRepository,
acceptLicense: AcceptLicense,
quiet: Quiet,
reinstall: Reinstall,
force: false,
trustRepository: TrustRepository,
noClobber: false,
credential: Credential,
requiredResourceFile: null,
requiredResourceJson: null,
requiredResourceHash: null,
specifiedPath: null,
asNupkg: false,
includeXML: true,
pathsToInstallPkg: _pathsToInstallPkg);
}
#endregion
}
}
Loading