From 707a557a591621633e04834513668dc0af6a8ce2 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 21 Sep 2021 02:07:16 -0400 Subject: [PATCH 01/18] implement code in FindPSResource and create PSIncludedResourceInfo class --- src/PSGet.Format.ps1xml | 26 +++++++ src/code/FindPSResource.cs | 139 +++++++++++++++++++++++++++++++++---- src/code/PSResourceInfo.cs | 23 ++++++ 3 files changed, 173 insertions(+), 15 deletions(-) diff --git a/src/PSGet.Format.ps1xml b/src/PSGet.Format.ps1xml index 80decb5de..4c8e87294 100644 --- a/src/PSGet.Format.ps1xml +++ b/src/PSGet.Format.ps1xml @@ -25,5 +25,31 @@ + + PSIncludedResourceInfo + + Microsoft.PowerShell.PowerShellGet.UtilClasses.PSIncludedResourceInfo + + + + + + + + + + + + + Name + ParentResource.Version + ParentResource.PrereleaseLabel + ParentResource.Name + ParentResource.Repository + + + + + diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 1e576ad29..39c9b65db 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -134,11 +134,11 @@ public sealed class FindPSResource : PSCmdlet protected override void BeginProcessing() { _source = new CancellationTokenSource(); - _cancellationToken = _source.Token; - - // Create a respository story (the PSResourceRepository.xml file) if it does not already exist - // This is to create a better experience for those who have just installed v3 and want to get up and running quickly - RepositorySettings.CheckRepositoryStore(); + _cancellationToken = _source.Token; + + // Create a respository story (the PSResourceRepository.xml file) if it does not already exist + // This is to create a better experience for those who have just installed v3 and want to get up and running quickly + RepositorySettings.CheckRepositoryStore(); } protected override void StopProcessing() @@ -155,19 +155,11 @@ protected override void ProcessRecord() break; case CommandNameParameterSet: - ThrowTerminatingError(new ErrorRecord( - new PSNotImplementedException("CommandNameParameterSet is not yet implemented. Please rerun cmdlet with other parameter set."), - "CommandParameterSetNotImplementedYet", - ErrorCategory.NotImplemented, - this)); + ProcessCommandOrDscParameterSet(); break; case DscResourceNameParameterSet: - ThrowTerminatingError(new ErrorRecord( - new PSNotImplementedException("DscResourceNameParameterSet is not yet implemented. Please rerun cmdlet with other parameter set."), - "DscResourceParameterSetNotImplementedYet", - ErrorCategory.NotImplemented, - this)); + ProcessCommandOrDscParameterSet(); break; default: @@ -256,6 +248,123 @@ private void ProcessResourceNameParameterSet() } } + private void ProcessCommandOrDscParameterSet() + { + // can have commandName + // or have commandName + moduleName + // cannot have Command + DSCResource BOTH. bc one pset called at a time + // cannot have neither Command nor DSCResource, bc pset wouldn't have been called. + // add Dbg.Assert? + bool isSearchingForCommands = (DscResourceName == null || DscResourceName.Length == 0); + var commandOrDSCNamesToSearch = Utils.ProcessNameWildcards(isSearchingForCommands ? CommandName : DscResourceName, + out string[] errorMsgs, + out bool nameContainsWildcard); + + 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 commandOrDSCNamesToSearch + if (commandOrDSCNamesToSearch.Length == 0) + { + return; + } + + if (String.Equals(commandOrDSCNamesToSearch[0], "*", StringComparison.InvariantCultureIgnoreCase)) + { + // WriteVerbose("Resource names were detected to be (or contain an element equal to): '*', so all packages will be updated"); + WriteError(new ErrorRecord( + new PSInvalidOperationException("-CommandName '*' or -DSCResourceName '*' is not supported for Find-PSResource so all CommandName or DSCResourceName entries will be discarded."), + "CommandDSCResourceNameEqualsWildcardIsNotSupported", + ErrorCategory.InvalidArgument, + this)); + return; + } + + // if ModuleName not specified search all packages (Name '*') w/ Type Command or DSC + // if ModuleName is specified, provide that new string[] {ModuleName} as Name w/ that type + + FindHelper findHelper = new FindHelper(_cancellationToken, this); + List foundPackages = new List(); + + if (String.IsNullOrEmpty(ModuleName)) + { + foreach (PSResourceInfo package in findHelper.FindByResourceName( + name: new string[]{"*"}, + type: isSearchingForCommands? ResourceType.Command : ResourceType.DscResource, + version: Version, + prerelease: Prerelease, + tag: Tag, + repository: Repository, + credential: Credential, + includeDependencies: IncludeDependencies)) + { + foundPackages.Add(package); + } + } + else + { + foreach (PSResourceInfo package in findHelper.FindByResourceName( + name: new string[]{ModuleName}, + type: isSearchingForCommands ? ResourceType.Command : ResourceType.DscResource, + version: Version, + prerelease: Prerelease, + tag: Tag, + repository: Repository, + credential: Credential, + includeDependencies: IncludeDependencies)) + { + foundPackages.Add(package); + } + } + + WriteVerbose("packages before type filtering by name: " + foundPackages.Count()); + WriteVerbose("namesToSearch count: " + commandOrDSCNamesToSearch.Count()); + + // -CommandName "command1", "dsc1" <- should not return or add DSC name + List resourcesWithCorrectCommandOrDSC = new List(); + foreach (string resourceName in commandOrDSCNamesToSearch) + { + WriteVerbose("resource name: " + resourceName); + // TODO: question here, if package contained multiple commands we are interested in, + // we'd return: + // Command1 , PackageA + // Command2 , PackageB (right?, not make the packages unique! so I think below is ok) + foreach (var uniquePkgsWithType in foundPackages) + { + // WriteVerbose("uniquepkg name: " + uniquePkgsWithType.Name); + if (isSearchingForCommands && uniquePkgsWithType.Includes.Command.Contains(resourceName)) + { + resourcesWithCorrectCommandOrDSC.Add(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); + WriteVerbose("Command Added " + resourceName + " from " + uniquePkgsWithType.Name); + } + else if (!isSearchingForCommands && uniquePkgsWithType.Includes.DscResource.Contains(resourceName)) + { + resourcesWithCorrectCommandOrDSC.Add(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); + WriteVerbose("DSC Added " + resourceName + " from " + uniquePkgsWithType.Name); + } + } + } + + foreach (PSIncludedResourceInfo resource in resourcesWithCorrectCommandOrDSC) + { + WriteObject(resource); + } + + + // foreach (var uniquePackageVersion in foundPackages.GroupBy( + // m => new {m.Name, m.Version}).Select( + // group => group.First()).ToList()) + // { + // WriteObject(uniquePackageVersion); + // } + } #endregion } } diff --git a/src/code/PSResourceInfo.cs b/src/code/PSResourceInfo.cs index a70922618..fb415b7c8 100644 --- a/src/code/PSResourceInfo.cs +++ b/src/code/PSResourceInfo.cs @@ -199,6 +199,29 @@ public Dependency(string dependencyName, VersionRange dependencyVersionRange) #endregion + #region PSIncludedResourceInfo + public sealed class PSIncludedResourceInfo + { + // this object will represent a Command or DSCResource or Function + // included by the PSResourceInfo property + + #region Properties + public string Name { get; } + + public PSResourceInfo ParentResource { get; } + #endregion + + #region Constructor + public PSIncludedResourceInfo(string name, PSResourceInfo parentResource) + { + Name = name; + ParentResource = parentResource; + } + #endregion + } + + #endregion + #region PSResourceInfo public sealed class PSResourceInfo From 51580566c14eef04cf02d87fb82b308e572b7285 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 21 Sep 2021 12:22:39 -0400 Subject: [PATCH 02/18] get includes info in PSResourceInfo.TryConvert() from tags --- src/PSGet.Format.ps1xml | 8 ++++---- src/code/PSResourceInfo.cs | 29 +++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/PSGet.Format.ps1xml b/src/PSGet.Format.ps1xml index 4c8e87294..92b92a4f4 100644 --- a/src/PSGet.Format.ps1xml +++ b/src/PSGet.Format.ps1xml @@ -42,10 +42,10 @@ Name - ParentResource.Version - ParentResource.PrereleaseLabel - ParentResource.Name - ParentResource.Repository + ($this.ParentResource.Version) + ($this.ParentResource.PrereleaseLabel) + ($this.ParentResource.Name) + ($this.ParentResource.Repository) diff --git a/src/code/PSResourceInfo.cs b/src/code/PSResourceInfo.cs index fb415b7c8..e37e6117a 100644 --- a/src/code/PSResourceInfo.cs +++ b/src/code/PSResourceInfo.cs @@ -508,7 +508,14 @@ public static bool TryConvert( } try - { + { + var typeInfo = ParseMetadataType(metadataToParse, repositoryName, type, out ArrayList commandNames, out ArrayList dscResourceNames); + var resourceHashtable = new Hashtable(); + resourceHashtable.Add(nameof(PSResourceInfo.Includes.Command), new PSObject(commandNames)); + resourceHashtable.Add(nameof(PSResourceInfo.Includes.DscResource), new PSObject(dscResourceNames)); + var includes = new ResourceIncludes(resourceHashtable); + + psGetInfo = new PSResourceInfo( additionalMetadata: null, author: ParseMetadataAuthor(metadataToParse), @@ -517,7 +524,7 @@ public static bool TryConvert( dependencies: ParseMetadataDependencies(metadataToParse), description: ParseMetadataDescription(metadataToParse), iconUri: ParseMetadataIconUri(metadataToParse), - includes: null, + includes: includes, installedDate: null, installedLocation: null, isPrelease: ParseMetadataIsPrerelease(metadataToParse), @@ -532,7 +539,8 @@ public static bool TryConvert( repository: repositoryName, repositorySourceLocation: null, tags: ParseMetadataTags(metadataToParse), - type: ParseMetadataType(metadataToParse, repositoryName, type), + // type: ParseMetadataType(metadataToParse, repositoryName, type), + type: typeInfo, updatedDate: null, version: ParseMetadataVersion(metadataToParse)); @@ -826,7 +834,11 @@ private static string[] ParseMetadataTags(IPackageSearchMetadata pkg) return pkg.Tags.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries); } - private static ResourceType ParseMetadataType(IPackageSearchMetadata pkg, string repoName, ResourceType? pkgType) + private static ResourceType ParseMetadataType(IPackageSearchMetadata pkg, + string repoName, + ResourceType? pkgType, + out ArrayList commandNames, + out ArrayList dscResourceNames) { // possible type combinations: // M, C @@ -834,6 +846,8 @@ private static ResourceType ParseMetadataType(IPackageSearchMetadata pkg, string // M // S + commandNames = new ArrayList(); + dscResourceNames = new ArrayList(); string[] tags = ParseMetadataTags(pkg); ResourceType currentPkgType = ResourceType.Module; @@ -861,15 +875,18 @@ private static ResourceType ParseMetadataType(IPackageSearchMetadata pkg, string currentPkgType &= ~ResourceType.Module; currentPkgType |= ResourceType.Script; } - if (tag.StartsWith("PSCommand_")) + if (tag.StartsWith("PSCommand_", StringComparison.InvariantCultureIgnoreCase)) { currentPkgType |= ResourceType.Command; + commandNames.Add(tag.Split('_')[1]); } - if (String.Equals(tag, "PSIncludes_DscResource", StringComparison.InvariantCultureIgnoreCase)) + if (tag.StartsWith("PSDscResource_", StringComparison.InvariantCultureIgnoreCase)) { currentPkgType |= ResourceType.DscResource; + dscResourceNames.Add(tag.Split('_')[1]); } } + return currentPkgType; } From 4dfd19c03384d84123ddf1f2da173c52ef1a032e Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 21 Sep 2021 12:47:45 -0400 Subject: [PATCH 03/18] clean up code --- src/code/FindPSResource.cs | 71 +++++++++++--------------------------- 1 file changed, 21 insertions(+), 50 deletions(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 39c9b65db..2bbf8e550 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -278,7 +278,6 @@ private void ProcessCommandOrDscParameterSet() if (String.Equals(commandOrDSCNamesToSearch[0], "*", StringComparison.InvariantCultureIgnoreCase)) { - // WriteVerbose("Resource names were detected to be (or contain an element equal to): '*', so all packages will be updated"); WriteError(new ErrorRecord( new PSInvalidOperationException("-CommandName '*' or -DSCResourceName '*' is not supported for Find-PSResource so all CommandName or DSCResourceName entries will be discarded."), "CommandDSCResourceNameEqualsWildcardIsNotSupported", @@ -287,58 +286,37 @@ private void ProcessCommandOrDscParameterSet() return; } - // if ModuleName not specified search all packages (Name '*') w/ Type Command or DSC - // if ModuleName is specified, provide that new string[] {ModuleName} as Name w/ that type - FindHelper findHelper = new FindHelper(_cancellationToken, this); List foundPackages = new List(); - if (String.IsNullOrEmpty(ModuleName)) - { - foreach (PSResourceInfo package in findHelper.FindByResourceName( - name: new string[]{"*"}, - type: isSearchingForCommands? ResourceType.Command : ResourceType.DscResource, - version: Version, - prerelease: Prerelease, - tag: Tag, - repository: Repository, - credential: Credential, - includeDependencies: IncludeDependencies)) - { - foundPackages.Add(package); - } - } - else + foreach (PSResourceInfo package in findHelper.FindByResourceName( + name: String.IsNullOrEmpty(ModuleName) ? new string[]{"*"} : new string[]{ModuleName}, + type: isSearchingForCommands? ResourceType.Command : ResourceType.DscResource, + version: Version, + prerelease: Prerelease, + tag: Tag, + repository: Repository, + credential: Credential, + includeDependencies: IncludeDependencies)) { - foreach (PSResourceInfo package in findHelper.FindByResourceName( - name: new string[]{ModuleName}, - type: isSearchingForCommands ? ResourceType.Command : ResourceType.DscResource, - version: Version, - prerelease: Prerelease, - tag: Tag, - repository: Repository, - credential: Credential, - includeDependencies: IncludeDependencies)) - { - foundPackages.Add(package); - } + foundPackages.Add(package); } - - WriteVerbose("packages before type filtering by name: " + foundPackages.Count()); - WriteVerbose("namesToSearch count: " + commandOrDSCNamesToSearch.Count()); - + // -CommandName "command1", "dsc1" <- should not return or add DSC name List resourcesWithCorrectCommandOrDSC = new List(); + + // TODO: question here, if package contained multiple commands we are interested in, + // we'd return: + // Command1 , PackageA + // Command2 , PackageB (right?, not make the packages unique! so I think below is ok) + foundPackages = foundPackages.GroupBy( + m => new {m.Name, m.Version}).Select( + group => group.First()).ToList(); + foreach (string resourceName in commandOrDSCNamesToSearch) { - WriteVerbose("resource name: " + resourceName); - // TODO: question here, if package contained multiple commands we are interested in, - // we'd return: - // Command1 , PackageA - // Command2 , PackageB (right?, not make the packages unique! so I think below is ok) foreach (var uniquePkgsWithType in foundPackages) { - // WriteVerbose("uniquepkg name: " + uniquePkgsWithType.Name); if (isSearchingForCommands && uniquePkgsWithType.Includes.Command.Contains(resourceName)) { resourcesWithCorrectCommandOrDSC.Add(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); @@ -356,15 +334,8 @@ private void ProcessCommandOrDscParameterSet() { WriteObject(resource); } - - - // foreach (var uniquePackageVersion in foundPackages.GroupBy( - // m => new {m.Name, m.Version}).Select( - // group => group.First()).ToList()) - // { - // WriteObject(uniquePackageVersion); - // } } + #endregion } } From 4eb024474017b6b44d42b947758cb3f1da68d1a8 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 21 Sep 2021 13:59:39 -0400 Subject: [PATCH 04/18] add tests for CommandName and DSCResourceName parameter sets --- test/FindPSResource.Tests.ps1 | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/FindPSResource.Tests.ps1 b/test/FindPSResource.Tests.ps1 index 71805f03c..1d2553d1f 100644 --- a/test/FindPSResource.Tests.ps1 +++ b/test/FindPSResource.Tests.ps1 @@ -239,4 +239,40 @@ Describe 'Test Find-PSResource for Module' { $resNonDefault = Find-PSResource -Name $moduleName -Repository $repoLowerPriorityRanking $resNonDefault.Repository | Should -Be $repoLowerPriorityRanking } + + It "find resource given CommandName (CommandNameParameterSet)" { + $commandName = "Get-TargetResource" + $res = Find-PSResource -CommandName $commandName -Repository $PSGalleryName + foreach ($item in $res) { + $item.Name | Should -Be $commandName + $item.ParentResource.Includes.Command | Should -Contain $commandName + } + } + + It "find resource given CommandName and ModuleName (CommandNameParameterSet)" { + $commandName = "Get-TargetResource" + $moduleName = "SystemLocaleDsc" + $res = Find-PSResource -CommandName $commandName -ModuleName $moduleName -Repository $PSGalleryName + $res.Name | Should -Be $commandName + $res.ParentResource.Name | Should -Be $moduleName + $res.ParentResource.Includes.Command | Should -Contain $commandName + } + + It "find resource given DSCResourceName (DSCResourceNameParameterSet)" { + $dscResourceName = "SystemLocale" + $res = Find-PSResource -DscResourceName $dscResourceName -Repository $PSGalleryName + foreach ($item in $res) { + $item.Name | Should -Be $dscResourceName + $item.ParentResource.Includes.DscResource | Should -Contain $dscResourceName + } + } + + It "find resource given DscResourceName and ModuleName (DSCResourceNameParameterSet)" { + $dscResourceName = "SystemLocale" + $moduleName = "SystemLocaleDsc" + $res = Find-PSResource -DscResourceName $dscResourceName -ModuleName $moduleName -Repository $PSGalleryName + $res.Name | Should -Be $dscResourceName + $res.ParentResource.Name | Should -Be $moduleName + $res.ParentResource.Includes.DscResource | Should -Contain $dscResourceName + } } From f299e4642a3241fb2bb77e1cd13a4f8d98eee642 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 21 Sep 2021 15:41:16 -0400 Subject: [PATCH 05/18] resolve TODO comments --- src/PSGet.Format.ps1xml | 14 +++++++-- src/code/FindPSResource.cs | 54 +++++++++++++++++++---------------- test/FindPSResource.Tests.ps1 | 3 ++ 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/PSGet.Format.ps1xml b/src/PSGet.Format.ps1xml index 92b92a4f4..25a734941 100644 --- a/src/PSGet.Format.ps1xml +++ b/src/PSGet.Format.ps1xml @@ -25,7 +25,7 @@ - + diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 2bbf8e550..7a9dae6ef 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -76,7 +76,7 @@ public sealed class FindPSResource : PSCmdlet [Parameter(ParameterSetName = CommandNameParameterSet)] [Parameter(ParameterSetName = DscResourceNameParameterSet)] [ValidateNotNullOrEmpty] - public string ModuleName { get; set; } + public string[] ModuleName { get; set; } /// /// Specifies a list of command names that searched module packages will provide. Wildcards are supported. @@ -250,21 +250,27 @@ private void ProcessResourceNameParameterSet() private void ProcessCommandOrDscParameterSet() { - // can have commandName - // or have commandName + moduleName - // cannot have Command + DSCResource BOTH. bc one pset called at a time - // cannot have neither Command nor DSCResource, bc pset wouldn't have been called. - // add Dbg.Assert? bool isSearchingForCommands = (DscResourceName == null || DscResourceName.Length == 0); - var commandOrDSCNamesToSearch = Utils.ProcessNameWildcards(isSearchingForCommands ? CommandName : DscResourceName, - out string[] errorMsgs, - out bool nameContainsWildcard); - + var commandOrDSCNamesToSearch = Utils.ProcessNameWildcards( + pkgNames: isSearchingForCommands ? CommandName : DscResourceName, + errorMsgs: out string[] errorMsgs, + isContainWildcard: out bool nameContainsWildcard); + + if (nameContainsWildcard) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException("Wilcards are not supported for -CommandName or -DSCResourceName for Find-PSResource. So all CommandName or DSCResourceName entries will be discarded."), + "CommandDSCResourceNameWithWildcardsNotSupported", + ErrorCategory.InvalidArgument, + this)); + return; + } + foreach (string error in errorMsgs) { WriteError(new ErrorRecord( new PSInvalidOperationException(error), - "ErrorFilteringNamesForUnsupportedWildcards", + "ErrorFilteringCommandDscResourceNamesForUnsupportedWildcards", ErrorCategory.InvalidArgument, this)); } @@ -275,22 +281,27 @@ private void ProcessCommandOrDscParameterSet() { return; } + + var moduleNamesToSearch = Utils.ProcessNameWildcards( + pkgNames: ModuleName, + errorMsgs: out string[] moduleErrorMsgs, + isContainWildcard: out bool _); - if (String.Equals(commandOrDSCNamesToSearch[0], "*", StringComparison.InvariantCultureIgnoreCase)) + foreach (string error in moduleErrorMsgs) { WriteError(new ErrorRecord( - new PSInvalidOperationException("-CommandName '*' or -DSCResourceName '*' is not supported for Find-PSResource so all CommandName or DSCResourceName entries will be discarded."), - "CommandDSCResourceNameEqualsWildcardIsNotSupported", + new PSInvalidOperationException(error), + "ErrorFilteringModuleNamesForUnsupportedWildcards", ErrorCategory.InvalidArgument, this)); - return; } FindHelper findHelper = new FindHelper(_cancellationToken, this); List foundPackages = new List(); foreach (PSResourceInfo package in findHelper.FindByResourceName( - name: String.IsNullOrEmpty(ModuleName) ? new string[]{"*"} : new string[]{ModuleName}, + name: moduleNamesToSearch, + // provide type so Scripts endpoint for PSGallery won't be searched type: isSearchingForCommands? ResourceType.Command : ResourceType.DscResource, version: Version, prerelease: Prerelease, @@ -302,21 +313,16 @@ private void ProcessCommandOrDscParameterSet() foundPackages.Add(package); } - // -CommandName "command1", "dsc1" <- should not return or add DSC name List resourcesWithCorrectCommandOrDSC = new List(); - // TODO: question here, if package contained multiple commands we are interested in, - // we'd return: + // if package contained multiple commands we are interested in, we'd return: // Command1 , PackageA - // Command2 , PackageB (right?, not make the packages unique! so I think below is ok) - foundPackages = foundPackages.GroupBy( - m => new {m.Name, m.Version}).Select( - group => group.First()).ToList(); - + // Command2 , PackageA foreach (string resourceName in commandOrDSCNamesToSearch) { foreach (var uniquePkgsWithType in foundPackages) { + // -CommandName "command1", "dsc1" <- (will not return or add DSC name) if (isSearchingForCommands && uniquePkgsWithType.Includes.Command.Contains(resourceName)) { resourcesWithCorrectCommandOrDSC.Add(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); diff --git a/test/FindPSResource.Tests.ps1 b/test/FindPSResource.Tests.ps1 index 1d2553d1f..2bc2b4bfd 100644 --- a/test/FindPSResource.Tests.ps1 +++ b/test/FindPSResource.Tests.ps1 @@ -9,6 +9,9 @@ Describe 'Test Find-PSResource for Module' { $TestGalleryName = Get-PoshTestGalleryName $PSGalleryName = Get-PSGalleryName $NuGetGalleryName = Get-NuGetGalleryName + $commandName = "Get-TargetResource" + $dscResourceName = "SystemLocale" + $parentModuleName = "SystemLocaleDsc" Get-NewPSResourceRepositoryFile Register-LocalRepos } From 38b4e0e7973d5d5127d3d7bc5655e91dcc5d7927 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 21 Sep 2021 20:02:35 -0400 Subject: [PATCH 06/18] fix formatting of PSIncludedResourceInfo --- src/PSGet.Format.ps1xml | 58 +++++++++++++++++++------------------- src/code/FindPSResource.cs | 3 +- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/PSGet.Format.ps1xml b/src/PSGet.Format.ps1xml index 25a734941..695dc2813 100644 --- a/src/PSGet.Format.ps1xml +++ b/src/PSGet.Format.ps1xml @@ -25,39 +25,39 @@ - + diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 7a9dae6ef..bbf575fc3 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -315,13 +315,14 @@ private void ProcessCommandOrDscParameterSet() List resourcesWithCorrectCommandOrDSC = new List(); - // if package contained multiple commands we are interested in, we'd return: + // if a single package contains multiple commands we are interested in, return a unique entry for each: // Command1 , PackageA // Command2 , PackageA foreach (string resourceName in commandOrDSCNamesToSearch) { foreach (var uniquePkgsWithType in foundPackages) { + // this check ensures DSC names provided as a Command name won't get returned mistakenly // -CommandName "command1", "dsc1" <- (will not return or add DSC name) if (isSearchingForCommands && uniquePkgsWithType.Includes.Command.Contains(resourceName)) { From 20e9613f21bf56e33f41045e7ed94e73af2f9b88 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 21 Sep 2021 20:46:23 -0400 Subject: [PATCH 07/18] clean up tests --- test/FindPSResource.Tests.ps1 | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/test/FindPSResource.Tests.ps1 b/test/FindPSResource.Tests.ps1 index 2bc2b4bfd..57ab7a23b 100644 --- a/test/FindPSResource.Tests.ps1 +++ b/test/FindPSResource.Tests.ps1 @@ -244,7 +244,6 @@ Describe 'Test Find-PSResource for Module' { } It "find resource given CommandName (CommandNameParameterSet)" { - $commandName = "Get-TargetResource" $res = Find-PSResource -CommandName $commandName -Repository $PSGalleryName foreach ($item in $res) { $item.Name | Should -Be $commandName @@ -253,16 +252,13 @@ Describe 'Test Find-PSResource for Module' { } It "find resource given CommandName and ModuleName (CommandNameParameterSet)" { - $commandName = "Get-TargetResource" - $moduleName = "SystemLocaleDsc" - $res = Find-PSResource -CommandName $commandName -ModuleName $moduleName -Repository $PSGalleryName + $res = Find-PSResource -CommandName $commandName -ModuleName $parentModuleName -Repository $PSGalleryName $res.Name | Should -Be $commandName - $res.ParentResource.Name | Should -Be $moduleName + $res.ParentResource.Name | Should -Be $parentModuleName $res.ParentResource.Includes.Command | Should -Contain $commandName } It "find resource given DSCResourceName (DSCResourceNameParameterSet)" { - $dscResourceName = "SystemLocale" $res = Find-PSResource -DscResourceName $dscResourceName -Repository $PSGalleryName foreach ($item in $res) { $item.Name | Should -Be $dscResourceName @@ -271,11 +267,9 @@ Describe 'Test Find-PSResource for Module' { } It "find resource given DscResourceName and ModuleName (DSCResourceNameParameterSet)" { - $dscResourceName = "SystemLocale" - $moduleName = "SystemLocaleDsc" - $res = Find-PSResource -DscResourceName $dscResourceName -ModuleName $moduleName -Repository $PSGalleryName + $res = Find-PSResource -DscResourceName $dscResourceName -ModuleName $parentModuleName -Repository $PSGalleryName $res.Name | Should -Be $dscResourceName - $res.ParentResource.Name | Should -Be $moduleName + $res.ParentResource.Name | Should -Be $parentModuleName $res.ParentResource.Includes.DscResource | Should -Contain $dscResourceName } } From 06aaff9258f660b75c4b0a088f65029f9c773461 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Mon, 27 Sep 2021 11:50:05 -0400 Subject: [PATCH 08/18] update help docs --- help/Find-PSResource.md | 45 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/help/Find-PSResource.md b/help/Find-PSResource.md index cac8dfa5b..82fbce245 100644 --- a/help/Find-PSResource.md +++ b/help/Find-PSResource.md @@ -19,13 +19,13 @@ Searches for packages from a repository (local or remote), based on `-Name` and ### CommandNameParameterSet ``` PowerShell -[[-CommandName] ] [-ModuleName ] [-Version ] [-Prerelease] [-Tag ] +[[-CommandName] ] [-ModuleName ] [-Version ] [-Prerelease] [-Tag ] [-Repository ] [-Credential ] [-IncludeDependencies] [-WhatIf] [-Confirm] [] ``` ### DscResourceNameParameterSet ``` PowerShell -[[-DscResourceName] ] [-ModuleName ] [-Version ] [-Prerelease] [-Tag ] +[[-DscResourceName] ] [-ModuleName ] [-Version ] [-Prerelease] [-Tag ] [-Repository ] [-Credential ] [-IncludeDependencies] [-WhatIf] [-Confirm] [] ``` @@ -77,6 +77,47 @@ PS C:\> Find-PSResource -Name "Microsoft.PowerShell.SecretManagement" -Version " This examples searches for the package with `-Name` "Microsoft.PowerShell.SecretManagement". It returns all versions which satisfy the specified `-Version` range by looking through the specified `-Repository` "PSGallery". At the time of writing this example those satisfying versions are: "0.9.1.0" and "1.0.0.0". +### Example 4 +```powershell +PS C:\> Find-PSResource -CommandName "Get-TargetResource" -Repository PSGallery + Name Version Prerelease ModuleName Repository + ---- ------- ---------- ---------- ---------- + Get-TargetResource 3.1.0.0 xPowerShellExecutionPolicy PSGallery + Get-TargetResource 1.0.0.4 WindowsDefender PSGallery + Get-TargetResource 1.2.0.0 SystemLocaleDsc PSGallery + Get-TargetResource 1.0.0.0 xInternetExplorerHomePage PSGallery + Get-TargetResource 4.0.1055.0 OctopusDSC PSGallery + Get-TargetResource 1.2.0.0 cRegFile PSGallery + Get-TargetResource 1.1.0.0 cWindowsErrorReporting PSGallery + Get-TargetResource 1.0.0.0 cVNIC PSGallery + Get-TargetResource 1.1.17.0 supVsts PSGallery + +``` + +This examples searches for all module resources with `-CommandName` "Get-TargetResource" from the `-Repository` PSGallery. It returns all the module resources which include a command named "Get-TargetResource" and also lists the following information for each module resource: version, name (displayed under ModuleName) and repository. To access the rest of the properties of the parent module resource, you can access the `$_.ParentResource` of the PSIncludedResourceInfo object returned from the CommandName parameter set. + +### Example 5 +```powershell +PS C:\> Find-PSResource -CommandName "Get-TargetResource" -ModuleName "SystemLocaleDsc" -Repository PSGallery + Name Version Prerelease ModuleName Repository + ---- ------- ---------- ---------- ---------- + Get-TargetResource 1.2.0.0 SystemLocaleDsc PSGallery +``` + +This examples searches for a module resource with a command named "Get-TargetResource" (via the `-CommandName` parameter), specifically from the module resource "SystemLocaleDsc" (via the `-ModuleName` parameter) from the `-Repository` PSGallery. The "SystemLocaleDsc" resource does indeed include a command named Get-TargetResource so this resource will be returned. The returned object lists the name of the command (displayed under Name) and the following information for the parent module resource: version, name (displayed under ModuleName) and repository. To access the rest of the properties of the parent module resource, you can access the `$_.ParentResource` of the PSIncludedResourceInfo object returned from the CommandName parameter set. + +### Example 6 +```powershell +PS C:\> Find-PSResource -DscResourceName "SystemLocale" -Repository PSGallery + Name Version Prerelease ModuleName Repository + ---- ------- ---------- ---------- ---------- + Get-TargetResource 8.5.0.0 ComputerManagementDsc PSGallery + Get-TargetResource 1.2.0.0 SystemLocaleDsc PSGallery + +``` + +This examples searches for all module resources with `-DscResourceName` "SystemLocale" from the `-Repository` PSGallery. It returns all the module resources which include a DSC resource named "SystemLocale" and also lists the following information for each module resource: version, name (displayed under ModuleName) and repository. To access the rest of the properties of the parent module resource, you can access the `$_.ParentResource` of the PSIncludedResourceInfo object returned from the DSCResourceName parameter set. + ## PARAMETERS ### -Credential From 8f3c030a68905f9e18199fbb44522edbbcca56aa Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 15:08:15 -0400 Subject: [PATCH 09/18] pass in isSearchingForCommands as arg to helper --- src/code/FindPSResource.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index bbf575fc3..a802696bf 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -155,11 +155,11 @@ protected override void ProcessRecord() break; case CommandNameParameterSet: - ProcessCommandOrDscParameterSet(); + ProcessCommandOrDscParameterSet(isSearchingForCommands: true); break; case DscResourceNameParameterSet: - ProcessCommandOrDscParameterSet(); + ProcessCommandOrDscParameterSet(isSearchingForCommands: false); break; default: @@ -248,9 +248,8 @@ private void ProcessResourceNameParameterSet() } } - private void ProcessCommandOrDscParameterSet() + private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) { - bool isSearchingForCommands = (DscResourceName == null || DscResourceName.Length == 0); var commandOrDSCNamesToSearch = Utils.ProcessNameWildcards( pkgNames: isSearchingForCommands ? CommandName : DscResourceName, errorMsgs: out string[] errorMsgs, From b89c75e6c78f3c47c80506bbb0191a8e628dbc97 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 16:35:45 -0400 Subject: [PATCH 10/18] Check if moduleNamesToSearch length is zero, and if so then make it * --- src/code/FindPSResource.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index a802696bf..c93a5a08d 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -295,6 +295,11 @@ private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) this)); } + if (moduleNamesToSearch.Length == 0) + { + moduleNamesToSearch = new string[] {"*"}; + } + FindHelper findHelper = new FindHelper(_cancellationToken, this); List foundPackages = new List(); From 7d240ddb7757157caa0e28dfbd97e4fffc0269ca Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 16:58:31 -0400 Subject: [PATCH 11/18] remove vebrose statements and write object as we find matches and simplify condition --- src/code/FindPSResource.cs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index c93a5a08d..782e88a5c 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -328,23 +328,13 @@ private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) { // this check ensures DSC names provided as a Command name won't get returned mistakenly // -CommandName "command1", "dsc1" <- (will not return or add DSC name) - if (isSearchingForCommands && uniquePkgsWithType.Includes.Command.Contains(resourceName)) + if ((isSearchingForCommands && uniquePkgsWithType.Includes.Command.Contains(resourceName)) || + (!isSearchingForCommands && uniquePkgsWithType.Includes.DscResource.Contains(resourceName))) { - resourcesWithCorrectCommandOrDSC.Add(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); - WriteVerbose("Command Added " + resourceName + " from " + uniquePkgsWithType.Name); - } - else if (!isSearchingForCommands && uniquePkgsWithType.Includes.DscResource.Contains(resourceName)) - { - resourcesWithCorrectCommandOrDSC.Add(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); - WriteVerbose("DSC Added " + resourceName + " from " + uniquePkgsWithType.Name); + WriteObject(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); } } } - - foreach (PSIncludedResourceInfo resource in resourcesWithCorrectCommandOrDSC) - { - WriteObject(resource); - } } #endregion From b559edd0c151c9f245cd05c8e1e89e459f3072e7 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 17:00:00 -0400 Subject: [PATCH 12/18] remove unncessary list --- src/code/FindPSResource.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 782e88a5c..0ac975bea 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -316,8 +316,6 @@ private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) { foundPackages.Add(package); } - - List resourcesWithCorrectCommandOrDSC = new List(); // if a single package contains multiple commands we are interested in, return a unique entry for each: // Command1 , PackageA From 3f5ee37f479865f8657b82c6209f5e16afa39b83 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 17:07:21 -0400 Subject: [PATCH 13/18] Use variable name package instead of uniqueTypePackage --- src/code/FindPSResource.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 0ac975bea..6c12246c8 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -322,14 +322,14 @@ private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) // Command2 , PackageA foreach (string resourceName in commandOrDSCNamesToSearch) { - foreach (var uniquePkgsWithType in foundPackages) + foreach (var package in foundPackages) { // this check ensures DSC names provided as a Command name won't get returned mistakenly // -CommandName "command1", "dsc1" <- (will not return or add DSC name) - if ((isSearchingForCommands && uniquePkgsWithType.Includes.Command.Contains(resourceName)) || - (!isSearchingForCommands && uniquePkgsWithType.Includes.DscResource.Contains(resourceName))) + if ((isSearchingForCommands && package.Includes.Command.Contains(resourceName)) || + (!isSearchingForCommands && package.Includes.DscResource.Contains(resourceName))) { - WriteObject(new PSIncludedResourceInfo(resourceName, uniquePkgsWithType)); + WriteObject(new PSIncludedResourceInfo(resourceName, package)); } } } From f06bfb838e82a83263398b632e8e85bdeb04f76d Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 17:10:58 -0400 Subject: [PATCH 14/18] rename variable to nameToSearch --- src/code/FindPSResource.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 6c12246c8..4361fcc51 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -320,16 +320,16 @@ private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) // if a single package contains multiple commands we are interested in, return a unique entry for each: // Command1 , PackageA // Command2 , PackageA - foreach (string resourceName in commandOrDSCNamesToSearch) + foreach (string nameToSearch in commandOrDSCNamesToSearch) { foreach (var package in foundPackages) { // this check ensures DSC names provided as a Command name won't get returned mistakenly // -CommandName "command1", "dsc1" <- (will not return or add DSC name) - if ((isSearchingForCommands && package.Includes.Command.Contains(resourceName)) || - (!isSearchingForCommands && package.Includes.DscResource.Contains(resourceName))) + if ((isSearchingForCommands && package.Includes.Command.Contains(nameToSearch)) || + (!isSearchingForCommands && package.Includes.DscResource.Contains(nameToSearch))) { - WriteObject(new PSIncludedResourceInfo(resourceName, package)); + WriteObject(new PSIncludedResourceInfo(nameToSearch, package)); } } } From 4dd20b86d90c027edf479ce4ad4c2ca6a910452b Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 17:12:40 -0400 Subject: [PATCH 15/18] add newline indent in PSREsourceInfo --- src/code/PSResourceInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/PSResourceInfo.cs b/src/code/PSResourceInfo.cs index e37e6117a..4827cf906 100644 --- a/src/code/PSResourceInfo.cs +++ b/src/code/PSResourceInfo.cs @@ -217,6 +217,7 @@ public PSIncludedResourceInfo(string name, PSResourceInfo parentResource) Name = name; ParentResource = parentResource; } + #endregion } From c79e7db720b6978ccfe6d51deeffeb9440e78fe2 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 17:16:14 -0400 Subject: [PATCH 16/18] add comment description for PSIncludedResourceInfo --- src/code/PSResourceInfo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/code/PSResourceInfo.cs b/src/code/PSResourceInfo.cs index 4827cf906..c25dd5f11 100644 --- a/src/code/PSResourceInfo.cs +++ b/src/code/PSResourceInfo.cs @@ -212,6 +212,13 @@ public sealed class PSIncludedResourceInfo #endregion #region Constructor + + /// + /// Constructor + /// + /// + /// Name of the command or DSC resource + /// the parent module resource the command or dsc resource belongs to public PSIncludedResourceInfo(string name, PSResourceInfo parentResource) { Name = name; From 4264abb8e8239af5c34b3375d30a023ce3628bc3 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 17:20:08 -0400 Subject: [PATCH 17/18] rename PSIncludedResourceInfo to PSCommandResourceInfo --- src/code/FindPSResource.cs | 2 +- src/code/PSResourceInfo.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 4361fcc51..05a1c3948 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -329,7 +329,7 @@ private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) if ((isSearchingForCommands && package.Includes.Command.Contains(nameToSearch)) || (!isSearchingForCommands && package.Includes.DscResource.Contains(nameToSearch))) { - WriteObject(new PSIncludedResourceInfo(nameToSearch, package)); + WriteObject(new PSCommandResourceInfo(nameToSearch, package)); } } } diff --git a/src/code/PSResourceInfo.cs b/src/code/PSResourceInfo.cs index c25dd5f11..5d681825c 100644 --- a/src/code/PSResourceInfo.cs +++ b/src/code/PSResourceInfo.cs @@ -199,10 +199,10 @@ public Dependency(string dependencyName, VersionRange dependencyVersionRange) #endregion - #region PSIncludedResourceInfo - public sealed class PSIncludedResourceInfo + #region PSCommandResourceInfo + public sealed class PSCommandResourceInfo { - // this object will represent a Command or DSCResource or Function + // this object will represent a Command or DSCResource // included by the PSResourceInfo property #region Properties @@ -219,7 +219,7 @@ public sealed class PSIncludedResourceInfo /// /// Name of the command or DSC resource /// the parent module resource the command or dsc resource belongs to - public PSIncludedResourceInfo(string name, PSResourceInfo parentResource) + public PSCommandResourceInfo(string name, PSResourceInfo parentResource) { Name = name; ParentResource = parentResource; From 265e6f337fa21c6b4c8f56821aea356a0d4099d3 Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Tue, 28 Sep 2021 18:00:00 -0400 Subject: [PATCH 18/18] add PSCommandResourceInfo type to OutputType attribute for Find --- src/code/FindPSResource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 05a1c3948..f317c4280 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -21,7 +21,7 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets "PSResource", DefaultParameterSetName = ResourceNameParameterSet, SupportsShouldProcess = true)] - [OutputType(typeof(PSResourceInfo))] + [OutputType(typeof(PSResourceInfo), typeof(PSCommandResourceInfo))] public sealed class FindPSResource : PSCmdlet { #region Members