ps/Modules/.build/Test-ModuleInclusion.ps1
2023-05-30 22:51:22 -07:00

473 lines
36 KiB
PowerShell

Function Test-ModuleInclusion {
<#
.SYNOPSIS
Checks all the modules in the solution to see if there are obvious circular dependencies or if the module includes a higher-order include
.EXAMPLE
Test-ModuleInclusion .\
.PARAMETER FolderPath
The name of the folder to examine all files under.
.PARAMETER FailBuild
Throws if this is true
.PARAMETER ShowObviousCycles
Show obvious cycles. This is not as important as higher-order inclusion on lower-order modules
#>
[CmdletBinding()]
Param (
[string]$FolderPath,
[switch]$FailBuild,
[switch]$ShowObviousCycles
)
$cSharpCode = @"
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Collections;
public static class ModuleChecker {
#region static decls
static string[] verbs = new[] { "Add", "Approve", "Assert", "Backup", "Block", "Checkpoint", "Clear", "Close", "Compare", "Complete", "Compress", "Confirm", "Connect", "Convert", "ConvertFrom", "ConvertTo", "Copy", "Debug", "Deny", "Disable", "Disconnect", "Dismount", "Edit", "Enable", "Enter", "Exit", "Expand", "Export", "Find", "Format", "Get", "Grant", "Group", "Hide", "Import", "Initialize", "Install", "Invoke", "Join", "Limit", "Lock", "Measure", "Merge", "Mount", "Move", "New", "Open", "Optimize", "Out", "Ping", "Pop", "Protect", "Publish", "Push", "Read", "Receive", "Redo", "Register", "Remove", "Rename", "Repair", "Request", "Reset", "Resize", "Resolve", "Restart", "Restore", "Resume", "Revoke", "Save", "Search", "Select", "Send", "Set", "Show", "Skip", "Split", "Start", "Step", "Stop", "Submit", "Suspend", "Switch", "Sync", "Test", "Trace", "Unblock", "Undo", "Uninstall", "Unlock", "Unprotect", "Unpublish", "Unregister", "Update", "Use", "Wait", "Watch", "Write" };
static string[] webAdministrationFunctions = new[] { "Add-WebConfiguration", "Add-WebConfigurationLock", "Add-WebConfigurationProperty", "Backup-WebConfiguration", "Clear-WebCentralCertProvider", "Clear-WebConfiguration", "Clear-WebRequestTracingSetting", "Clear-WebRequestTracingSettings", "ConvertTo-WebApplication", "Disable-WebCentralCertProvider", "Disable-WebGlobalModule", "Disable-WebRequestTracing", "Enable-WebCentralCertProvider", "Enable-WebGlobalModule", "Enable-WebRequestTracing", "Get-WebAppDomain", "Get-WebApplication", "Get-WebAppPoolState", "Get-WebBinding", "Get-WebCentralCertProvider", "Get-WebConfigFile", "Get-WebConfiguration", "Get-WebConfigurationBackup", "Get-WebConfigurationLocation", "Get-WebConfigurationLock", "Get-WebConfigurationProperty", "Get-WebFilePath", "Get-WebGlobalModule", "Get-WebHandler", "Get-WebItemState", "Get-WebManagedModule", "Get-WebRequest", "Get-Website", "Get-WebsiteState", "Get-WebURL", "Get-WebVirtualDirectory", "New-WebApplication", "New-WebAppPool", "New-WebBinding", "New-WebFtpSite", "New-WebGlobalModule", "New-WebHandler", "New-WebManagedModule", "New-Website", "New-WebVirtualDirectory", "Remove-WebApplication", "Remove-WebAppPool", "Remove-WebBinding", "Remove-WebConfigurationBackup", "Remove-WebConfigurationLocation", "Remove-WebConfigurationLock", "Remove-WebConfigurationProperty", "Remove-WebGlobalModule", "Remove-WebHandler", "Remove-WebManagedModule", "Remove-Website", "Remove-WebVirtualDirectory", "Rename-WebConfigurationLocation", "Restart-WebAppPool", "Restart-WebItem", "Restore-WebConfiguration", "Select-WebConfiguration", "Set-WebBinding", "Set-WebCentralCertProvider", "Set-WebCentralCertProviderCredential", "Set-WebConfiguration", "Set-WebConfigurationProperty", "Set-WebGlobalModule", "Set-WebHandler", "Set-WebManagedModule", "Start-WebAppPool", "Start-WebCommitDelay", "Start-WebItem", "Start-Website", "Stop-WebAppPool", "Stop-WebCommitDelay", "Stop-WebItem", "Stop-Website" };
static string[] carbonFunctions = new[] { "Add-CGroupMember", "Add-CIisDefaultDocument", "Add-CTrustedHost", "Add-GroupMember", "Add-GroupMembers", "Add-IisDefaultDocument", "Add-TrustedHost", "Add-TrustedHosts", "Assert-AdminPrivilege", "Assert-AdminPrivileges", "Assert-CAdminPrivilege", "Assert-CFirewallConfigurable", "Assert-CService", "Assert-FirewallConfigurable", "Assert-Service", "Clear-CDscLocalResourceCache", "Clear-CMofAuthoringMetadata", "Clear-CTrustedHost", "Clear-DscLocalResourceCache", "Clear-MofAuthoringMetadata", "Clear-TrustedHost", "Clear-TrustedHosts", "Complete-CJob", "Complete-Job", "Complete-Jobs", "Compress-CItem", "Compress-Item", "Convert-CSecureStringToString", "Convert-CXmlFile", "Convert-SecureStringToString", "Convert-XmlFile", "ConvertFrom-Base64", "ConvertFrom-CBase64", "ConvertTo-Base64", "ConvertTo-CBase64", "ConvertTo-CContainerInheritanceFlags", "ConvertTo-CInheritanceFlag", "ConvertTo-CPropagationFlag", "ConvertTo-CSecurityIdentifier", "ConvertTo-ContainerInheritanceFlags", "ConvertTo-FullPath", "ConvertTo-InheritanceFlag", "ConvertTo-InheritanceFlags", "ConvertTo-PropagationFlag", "ConvertTo-PropagationFlags", "ConvertTo-SecurityIdentifier", "Copy-CDscResource", "Copy-DscResource", "Disable-AclInheritance", "Disable-CAclInheritance", "Disable-CFirewallStatefulFtp", "Disable-CIEEnhancedSecurityConfiguration", "Disable-CIisSecurityAuthentication", "Disable-CNtfsCompression", "Disable-FirewallStatefulFtp", "Disable-IEEnhancedSecurityConfiguration", "Disable-IisSecurityAuthentication", "Disable-NtfsCompression", "Enable-AclInheritance", "Enable-CAclInheritance", "Enable-CFirewallStatefulFtp", "Enable-CIEActivationPermission", "Enable-CIisDirectoryBrowsing", "Enable-CIisSecurityAuthentication", "Enable-CIisSsl", "Enable-CNtfsCompression", "Enable-FirewallStatefulFtp", "Enable-IEActivationPermission", "Enable-IEActivationPermissions", "Enable-IisDirectoryBrowsing", "Enable-IisSecurityAuthentication", "Enable-IisSsl", "Enable-NtfsCompression", "Expand-CItem", "Expand-Item", "Find-ADUser", "Find-CADUser", "Format-ADSearchFilterValue", "Format-ADSpecialCharacters", "Format-CADSearchFilterValue", "Get-ADDomainController", "Get-CADDomainController", "Get-CCertificate", "Get-CCertificateStore", "Get-CComPermission", "Get-CComSecurityDescriptor", "Get-CDscError", "Get-CDscWinEvent", "Get-CFileShare", "Get-CFileSharePermission", "Get-CFirewallRule", "Get-CGroup", "Get-CHttpUrlAcl", "Get-CIPAddress", "Get-CIisAppPool", "Get-CIisApplication", "Get-CIisConfigurationSection", "Get-CIisHttpHeader", "Get-CIisHttpRedirect", "Get-CIisMimeMap", "Get-CIisSecurityAuthentication", "Get-CIisVersion", "Get-CIisWebsite", "Get-CMsi", "Get-CMsmqMessageQueue", "Get-CMsmqMessageQueuePath", "Get-CPathProvider", "Get-CPathToHostsFile", "Get-CPerformanceCounter", "Get-CPermission", "Get-CPowerShellModuleInstallPath", "Get-CPowershellPath", "Get-CPrivilege", "Get-CProgramInstallInfo", "Get-CRegistryKeyValue", "Get-CScheduledTask", "Get-CServiceAcl", "Get-CServiceConfiguration", "Get-CServicePermission", "Get-CServiceSecurityDescriptor", "Get-CSslCertificateBinding", "Get-CTrustedHost", "Get-CUser", "Get-CWmiLocalUserAccount", "Get-Certificate", "Get-CertificateStore", "Get-ComPermission", "Get-ComPermissions", "Get-ComSecurityDescriptor", "Get-DscError", "Get-DscWinEvent", "Get-FileShare", "Get-FileSharePermission", "Get-FirewallRule", "Get-FirewallRules", "Get-Group", "Get-HttpUrlAcl", "Get-IPAddress", "Get-IisAppPool", "Get-IisApplication", "Get-IisConfigurationSection", "Get-IisHttpHeader", "Get-IisHttpRedirect", "Get-IisMimeMap", "Get-IisSecurityAuthentication", "Get-IisVersion", "Get-IisWebsite", "Get-Msi", "Get-MsmqMessageQueue", "Get-MsmqMessageQueuePath", "Get-PathCanonicalCase", "Get-PathProvider", "Get-PathToHostsFile", "Get-PerformanceCounter", "Get-PerformanceCounters", "Get-Permission", "Get-Permissions", "Get-PowerShellModuleInstallPath", "Get-PowershellPath", "Get-Privilege", "Get-Privileges", "Get-ProgramInstallInfo", "Get-RegistryKeyValue", "Get-ScheduledTask", "Get-ServiceAcl", "Get-ServiceConfiguration", "Get-ServicePermission", "Get-ServicePermissions", "Get-ServiceSecurityDescriptor", "Get-SslCertificateBinding", "Get-SslCertificateBindings", "Get-TrustedHost", "Get-TrustedHosts", "Get-User", "Get-WmiLocalUserAccount", "Grant-CComPermission", "Grant-CHttpUrlPermission", "Grant-CMsmqMessageQueuePermission", "Grant-CPermission", "Grant-CPrivilege", "Grant-CServiceControlPermission", "Grant-CServicePermission", "Grant-ComPermission", "Grant-ComPermissions", "Grant-HttpUrlPermission", "Grant-MsmqMessageQueuePermission", "Grant-MsmqMessageQueuePermissions", "Grant-Permission", "Grant-Permissions", "Grant-Privilege", "Grant-ServiceControlPermission", "Grant-ServicePermission", "Initialize-CLcm", "Initialize-Lcm", "Install-CCertificate", "Install-CDirectory", "Install-CFileShare", "Install-CGroup", "Install-CIisAppPool", "Install-CIisApplication", "Install-CIisVirtualDirectory", "Install-CIisWebsite", "Install-CJunction", "Install-CMsi", "Install-CMsmq", "Install-CMsmqMessageQueue", "Install-CPerformanceCounter", "Install-CRegistryKey", "Install-CScheduledTask", "Install-CService", "Install-CUser", "Install-Certificate", "Install-Directory", "Install-FileShare", "Install-Group", "Install-IisAppPool", "Install-IisApplication", "Install-IisVirtualDirectory", "Install-IisWebsite", "Install-Junction", "Install-Msi", "Install-Msmq", "Install-MsmqMessageQueue", "Install-PerformanceCounter", "Install-RegistryKey", "Install-ScheduledTask", "Install-Service", "Install-SmbShare", "Install-User", "Invoke-AppCmd", "Invoke-CAppCmd", "Invoke-CPowerShell", "Invoke-PowerShell", "Invoke-WindowsInstaller", "Join-CIisVirtualPath", "Join-IisVirtualPath", "Lock-CIisConfigurationSection", "Lock-IisConfigurationSection", "New-CCredential", "New-CJunction", "New-CRsaKeyPair", "New-CTempDirectory", "New-Credential", "New-Junction", "New-RsaKeyPair", "New-TempDir", "New-TempDirectory", "Protect-Acl", "Protect-CString", "Protect-String", "Read-CFile", "Read-File", "Remove-CDotNetAppSetting", "Remove-CEnvironmentVariable", "Remove-CGroupMember", "Remove-CHostsEntry", "Remove-CIisMimeMap", "Remove-CIniEntry", "Remove-CJunction", "Remove-CRegistryKeyValue", "Remove-CSslCertificateBinding", "Remove-Certificate", "Remove-DotNetAppSetting", "Remove-EnvironmentVariable", "Remove-GroupMember", "Remove-HostsEntry", "Remove-IisMimeMap", "Remove-IisWebsite", "Remove-IniEntry", "Remove-Junction", "Remove-MsmqMessageQueue", "Remove-RegistryKeyValue", "Remove-Service", "Remove-SslCertificateBinding", "Remove-User", "Reset-CHostsFile", "Reset-CMsmqQueueManagerID", "Reset-HostsFile", "Reset-MsmqQueueManagerID", "Resolve-CFullPath", "Resolve-CIdentity", "Resolve-CIdentityName", "Resolve-CNetPath", "Resolve-CPathCase", "Resolve-CRelativePath", "Resolve-FullPath", "Resolve-Identity", "Resolve-IdentityName", "Resolve-NetPath", "Resolve-PathCase", "Resolve-RelativePath", "Restart-CRemoteService", "Restart-RemoteService", "Revoke-CComPermission", "Revoke-CHttpUrlPermission", "Revoke-CPermission", "Revoke-CPrivilege", "Revoke-CServicePermission", "Revoke-ComPermission", "Revoke-ComPermissions", "Revoke-HttpUrlPermission", "Revoke-Permission", "Revoke-Privilege", "Revoke-ServicePermission", "Set-CDotNetAppSetting", "Set-CDotNetConnectionString", "Set-CEnvironmentVariable", "Set-CHostsEntry", "Set-CIisHttpHeader", "Set-CIisHttpRedirect", "Set-CIisMimeMap", "Set-CIisWebsiteID", "Set-CIisWebsiteSslCertificate", "Set-CIisWindowsAuthentication", "Set-CIniEntry", "Set-CRegistryKeyValue", "Set-CServiceAcl", "Set-CSslCertificateBinding", "Set-CTrustedHost", "Set-DotNetAppSetting", "Set-DotNetConnectionString", "Set-EnvironmentVariable", "Set-HostsEntry", "Set-IisHttpHeader", "Set-IisHttpRedirect", "Set-IisMimeMap", "Set-IisWebsiteID", "Set-IisWebsiteSslCertificate", "Set-IisWindowsAuthentication", "Set-IniEntry", "Set-RegistryKeyValue", "Set-ServiceAcl", "Set-SslCertificateBinding", "Set-TrustedHost", "Set-TrustedHosts", "Split-CIni", "Split-Ini", "Start-CDscPullConfiguration", "Start-DscPullConfiguration", "Test-AdminPrivilege", "Test-AdminPrivileges", "Test-CAdminPrivilege", "Test-CDotNet", "Test-CDscTargetResource", "Test-CFileShare", "Test-CFirewallStatefulFtp", "Test-CGroup", "Test-CGroupMember", "Test-CIPAddress", "Test-CIdentity", "Test-CIisAppPool", "Test-CIisConfigurationSection", "Test-CIisSecurityAuthentication", "Test-CIisWebsite", "Test-CMsmqMessageQueue", "Test-CNtfsCompression", "Test-COSIs32Bit", "Test-COSIs64Bit", "Test-CPathIsJunction", "Test-CPerformanceCounter", "Test-CPerformanceCounterCategory", "Test-CPermission", "Test-CPowerShellIs32Bit", "Test-CPowerShellIs64Bit", "Test-CPrivilege", "Test-CRegistryKeyValue", "Test-CScheduledTask", "Test-CService", "Test-CSslCertificateBinding", "Test-CTypeDataMember", "Test-CUncPath", "Test-CUser", "Test-CWindowsFeature", "Test-CZipFile", "Test-DotNet", "Test-DscTargetResource", "Test-FileShare", "Test-FirewallStatefulFtp", "Test-Group", "Test-GroupMember", "Test-IPAddress", "Test-Identity", "Test-IisAppPool", "Test-IisAppPoolExists", "Test-IisConfigurationSection", "Test-IisSecurityAuthentication", "Test-IisWebsite", "Test-IisWebsiteExists", "Test-MsmqMessageQueue", "Test-NtfsCompression", "Test-OSIs32Bit", "Test-OSIs64Bit", "Test-PathIsJunction", "Test-PerformanceCounter", "Test-PerformanceCounterCategory", "Test-Permission", "Test-PowerShellIs32Bit", "Test-PowerShellIs64Bit", "Test-Privilege", "Test-RegistryKeyValue", "Test-ScheduledTask", "Test-Service", "Test-SslCertificateBinding", "Test-TypeDataMember", "Test-UncPath", "Test-User", "Test-WindowsFeature", "Test-ZipFile", "Uninstall-CCertificate", "Uninstall-CDirectory", "Uninstall-CFileShare", "Uninstall-CGroup", "Uninstall-CIisAppPool", "Uninstall-CIisWebsite", "Uninstall-CJunction", "Uninstall-CMsmqMessageQueue", "Uninstall-CPerformanceCounterCategory", "Uninstall-CScheduledTask", "Uninstall-CService", "Uninstall-CUser", "Uninstall-Certificate", "Uninstall-Directory", "Uninstall-FileShare", "Uninstall-Group", "Uninstall-IisAppPool", "Uninstall-IisWebsite", "Uninstall-Junction", "Uninstall-MsmqMessageQueue", "Uninstall-PerformanceCounterCategory", "Uninstall-ScheduledTask", "Uninstall-Service", "Uninstall-User", "Unlock-CIisConfigurationSection", "Unlock-IisConfigurationSection", "Unprotect-AclAccessRules", "Unprotect-CString", "Unprotect-String", "Write-CDscError", "Write-CFile", "Write-DscError", "Write-File" };
static string[] windowsFunctions = new[] { "Add-LocalGroupMember", "Add-Member", "Add-Type", "Add-WindowsFeature", "Clear-Host", "Close-SmbOpenFile", "Compare-Object", "Compress-Certificates", "Convert-Path", "ConvertFrom-Json", "ConvertTo-JSON", "ConvertTo-Json", "ConvertTo-SecureString", "ConvertTo-Xml", "Copy-Item", "Enable-WindowsOptionalFeature", "Enter-PSSession", "Exit-PSSession", "Export-PfxCertificate", "Format-List", "Format-Table", "Get-ADComputer", "Get-ADGroupMember", "Get-ADUser", "Get-Acl", "Get-CIMInstance", "Get-ChildItem", "Get-CimInstance", "Get-Content", "Get-Date", "Get-FileHash", "Get-Host", "Get-IISAppPool", "Get-IISSite", "Get-Item", "Get-ItemProperty", "Get-ItemPropertyValue", "Get-LocalGroupMember", "Get-Location", "Get-Member", "Get-Module", "Get-NetIPAddress", "Get-NetTCPConnection", "Get-PSCallStack", "Get-Process", "Get-Random", "Get-Service", "Get-SmbOpenFile", "Get-TimeZone", "Get-Unique", "Get-Variable", "Get-WinEvent", "Get-WindowsFeature", "Get-Childitem", "Group-Object", "Import-Certificate", "Import-Csv", "Import-Module", "Import-PfxCertificate", "Install-ADServiceAccount", "Install-WindowsFeature", "Invoke-Command", "Invoke-Expression", "Invoke-Pester", "Invoke-RestMethod", "Invoke-WebRequest", "Join-Path", "Join-path", "Move-Item", "New-EventLog", "New-Item", "New-ItemProperty", "New-Object", "New-PSDrive", "New-PSSession", "New-ScheduledTaskAction", "New-ScheduledTaskTrigger", "New-Service", "New-TimeSpan", "New-Variable", "New-WebServiceProxy", "Out-File", "Out-Null", "Out-String", "Out-null", "Pop-Location", "Push-Location", "Read-Host", "Receive-Job", "Register-ScheduledTask", "Remove-Item", "Remove-PSDrive", "Remove-PSSession", "Remove-item", "Rename-Item", "Resolve-DnsName", "Resolve-Path", "Select-Object", "Select-Xml", "Select-object", "Send-MailMessage", "Set-Acl", "Set-Alias", "Set-Content", "Set-ExecutionPolicy", "Set-ItemProperty", "Set-Location", "Set-Service", "Set-Variable", "Split-Path", "Start-Job", "Start-Process", "Start-Service", "Start-Sleep", "Stop-Process", "Stop-Service", "Test-ADServiceAccount", "Test-NetConnection", "Test-Path", "Wait-Job", "Write-Debug", "Write-Error", "Write-Host", "Write-Information", "Write-Output", "Write-Verbose", "Write-Warning" ,"Restart-Computer","Restart-Service","Invoke-Item","Get-Counter","ConvertTo-Html","New-Guid"};
static string[] awsFunctions = new[] { "Remove-S3Object", "Write-S3Object", "Get-S3Object", "Copy-S3Object", "Copy-ServiceFabricApplicationPackage", "New-ASLaunchConfiguration", "Set-ASInstanceHealth", "Get-EC2Image", "Get-EC2Instance", "Get-EC2NetworkInterface", "Get-ELB2LoadBalancer", "Get-ELB2TargetGroup", "Get-ElbHealthcheckEndpoints", "Enter-ASStandby", "Exit-ASStandby", "Get-ASAutoScalingGroup", "Get-ASAutoScalingInstance", "Get-ASInstanceHealth", "Get-ASLaunchConfiguration", "Get-SSMParameter" ,"Read-S3Object","Get-ELB2TargetHealth"};
static string[] serviceFabricFunctions = new[] { "Get-ServiceFabricApplication", "Get-ServiceFabricApplicationType", "Get-ServiceFabricApplicationUpgrade", "Get-ServiceFabricClusterConfiguration", "Get-ServiceFabricClusterConfigurationUpgradeStatus", "Get-ServiceFabricDeployedApplication", "Get-ServiceFabricDeployedCodePackage", "Get-ServiceFabricNode", "Get-ServiceFabricPartition", "Get-ServiceFabricRegisteredClusterCodeVersion", "Get-ServiceFabricService", "Start-ServiceFabricApplicationUpgrade", "Start-ServiceFabricClusterConfigurationUpgrade", "Start-ServiceFabricClusterUpgrade", "Unregister-ServiceFabricApplicationType", "Update-ServiceFabricService", "Remove-ServiceFabricApplication", "Remove-ServiceFabricCluster", "Register-ServiceFabricApplicationType", "Restart-ServiceFabricDeployedCodePackage", "New-ServiceFabricApplication", "New-ServiceFabricNodeConfiguration", "Connect-ServiceFabricCluster","Invoke-MinimizeEnvironment" };
static string[] cloudbase_powershell_yaml = new[] { "ConvertFrom-Yaml", "ConvertTo-Yaml" };
static string[] redisFunctions = new[] { "Invoke-RedisScript","Add-RedisKey" };
/// <summary>
/// Most of these fell out of comments because of the matching on verb-word
/// </summary>
static string[] ignoreRandomPhrases = new[] { "add-capability", "install-to", "install-type", "Install-To", "Write-out", "read-only", "test-case", "out-of", "use-case", "use-case", "out-of", "Request-Monitor", "read-to", "read-from", "read-only", "Select-Alkami",/*Used as demo files when generating a module.*/"Get-HelloWorld", "Get-HelloWorldInternal", /*Two aliases that are harder to revert than I expected*/"New-AlkamiWebAppPool", "Get-AlkamiWebAppPool","new-relic","open-block","exit-condition" };
static List<string> excludeNames = new List<string> { "VariableDeclarations", "ConfigurationValues" };
const string CarbonModuleName = "Carbon";
const string WebAdministrationModuleName = "WebAdministration";
const string WindowsModuleName = "Generic Windows";
const string AwsModuleName = "AWS";
const string CloudbaseModuleName = "Cloudbase";
const string RedisModuleName = "Redis";
const string ServiceFabricModuleName = "ServiceFabric";
const string IgnoredFunctionsModuleName = "ignore anything with this module name";
#endregion static decls
public static IEnumerable<ModuleFunctionDefinition> GetFunctionDefinitionsFromModule(DirectoryInfo directoryInfo, ModuleDefinition module, Regex regex) {
var functionDefinitions = new List<ModuleFunctionDefinition>();
var publicFiles = directoryInfo.GetDirectories("Public").FirstOrDefault();
if (publicFiles != null) {
foreach (var file in publicFiles.GetFiles("*.ps1")) {
var filename = Path.GetFileNameWithoutExtension(file.FullName);
if (
!(filename.EndsWith(".tests", StringComparison.InvariantCultureIgnoreCase) || filename.EndsWith(".test", StringComparison.InvariantCultureIgnoreCase))
&& filename.IndexOf("-") > 1
&& verbs.Contains(filename.Split('-')[0])
) {
var referencedFunctions = regex.Matches(File.ReadAllText(file.FullName)).OfType<Match>().SelectMany(m => m.Captures.OfType<Capture>().ToArray().Select(x => x.Value)).Distinct().Where(x => x.ToLowerInvariant() != filename.ToLowerInvariant());
var functionDefinition = new ModuleFunctionDefinition(filename, module, referencedFunctions);
functionDefinitions.Add(functionDefinition);
} else {
if (
!(filename.EndsWith(".tests", StringComparison.InvariantCultureIgnoreCase) || filename.EndsWith(".test", StringComparison.InvariantCultureIgnoreCase))
&& !excludeNames.Contains(filename)
) {
Console.WriteLine(string.Format("Did not match [{0}] as a valid filename.", file.Name));
}
}
}
}
var privateFiles = directoryInfo.GetDirectories("Private").FirstOrDefault();
if (privateFiles != null) {
foreach (var file in privateFiles.GetFiles("*.ps1")) {
var filename = Path.GetFileNameWithoutExtension(file.FullName);
if (
!(filename.EndsWith(".tests", StringComparison.InvariantCultureIgnoreCase) || filename.EndsWith(".test", StringComparison.InvariantCultureIgnoreCase))
&& filename.IndexOf("-") > 1
&& verbs.Contains(filename.Split('-')[0])) {
var referencedFunctions = regex.Matches(File.ReadAllText(file.FullName)).OfType<Match>().SelectMany(m => m.Captures.OfType<Capture>().ToArray().Select(x => x.Value)).Distinct();
var functionDefinition = new ModuleFunctionDefinition(filename, module, referencedFunctions) { IsPrivate = true };
functionDefinitions.Add(functionDefinition);
} else {
if (
!(filename.EndsWith(".tests", StringComparison.InvariantCultureIgnoreCase) || filename.EndsWith(".test", StringComparison.InvariantCultureIgnoreCase))
&& !excludeNames.Contains(filename)
) {
Console.WriteLine(string.Format("Did not match [{0}] as a valid filename.", file.Name));
}
}
}
}
return functionDefinitions;
}
public static bool DoIt(string searchPath, bool showObviousCycles = false) {
var matchVerbsString = string.Join("|", verbs);
var matchString = string.Format("({0})-\\w+",matchVerbsString);
var regex = new Regex(matchString, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
var allFoundFunctions = new List<ModuleFunctionDefinition>();
var allModules = new List<ModuleDefinition>();
#region pre-load ServiceFabric for reference
var sf = new ModuleDefinition(ServiceFabricModuleName) { IsStub = true, IsBase = true };
foreach (var function in serviceFabricFunctions) {
var fd = new ModuleFunctionDefinition(function, sf);
sf.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load Carbon for reference
#region pre-load AWS for reference
var aws = new ModuleDefinition(AwsModuleName) { IsStub = true, IsBase = true };
foreach (var function in awsFunctions) {
var fd = new ModuleFunctionDefinition(function, aws);
aws.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load AWS for reference
#region pre-load Carbon for reference
var carbon = new ModuleDefinition(CarbonModuleName) { IsBase = true };
foreach (var function in carbonFunctions) {
var fd = new ModuleFunctionDefinition(function, carbon);
carbon.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load Carbon for reference
#region pre-load WebAdministration for reference
var webAdministration = new ModuleDefinition(WebAdministrationModuleName) { IsBase = true };
foreach (var function in webAdministrationFunctions) {
var fd = new ModuleFunctionDefinition(function, webAdministration);
webAdministration.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load WebAdministration for reference
#region pre-load Windows for reference
var windows = new ModuleDefinition(WindowsModuleName) { IsStub = true, IsBase = true };
foreach (var function in windowsFunctions) {
var fd = new ModuleFunctionDefinition(function, windows);
windows.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load Windows for reference
#region pre-load ignored functions for reference
var ignored = new ModuleDefinition(IgnoredFunctionsModuleName) { IsStub = true, IsBase = true };
foreach (var function in ignoreRandomPhrases) {
var fd = new ModuleFunctionDefinition(function, ignored);
ignored.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load Ignored functions for reference
#region pre-load cloudbase for reference
var cloudbase = new ModuleDefinition(CloudbaseModuleName) { IsStub = true, IsBase = true };
foreach (var function in cloudbase_powershell_yaml) {
var fd = new ModuleFunctionDefinition(function, cloudbase);
windows.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load cloudbase for reference
#region pre-load redis for reference
var redis = new ModuleDefinition(RedisModuleName) { IsStub = true, IsBase = true };
foreach (var function in redisFunctions) {
var fd = new ModuleFunctionDefinition(function, redis);
aws.AddFunction(fd);
allFoundFunctions.Add(fd);
}
#endregion pre-load redis for reference
var modules = new DirectoryInfo(searchPath).GetFiles("*.psd1", SearchOption.AllDirectories);
foreach (var module in modules) {
var moduleName = Path.GetFileNameWithoutExtension(module.FullName);
var isCsharp = false;
if (module.Directory.GetFiles("*.csproj").Any()) {
Console.WriteLine(string.Format("Found a CS Project for {0}",moduleName));
isCsharp = true;
}
var moduleDefinition = new ModuleDefinition(moduleName) { IsCsharp = isCsharp };
var functionDefinitions = GetFunctionDefinitionsFromModule(module.Directory, moduleDefinition, regex);
moduleDefinition.AddFunctions(functionDefinitions);
allFoundFunctions.AddRange(functionDefinitions);
allModules.Add(moduleDefinition);
}
// Now that all the modules have been parsed and we have all the function definitions, we need to do something with the functions
// Let's parse the functions to find all the places they are used, and see what that web looks like.
// So basically, foreach function find modules they need to function.
// There may be more than one function defined in a given module, example: Get-Certificate in carbon and alkami.ops.certificates
Dictionary<string, ModuleFunctionDefinition> refDic = new Dictionary<string, ModuleFunctionDefinition>();
foreach (var function in allFoundFunctions) {
if (!refDic.ContainsKey(function.Name.ToLower())) {
refDic.Add(function.Name.ToLower(), function);
}
}
foreach (var module in allModules) {
foreach (var function in module.ModuleFunctionDefinitions) {
foreach (var name in function.ReferencedFunctions) {
if (function.ReferencedFunctions.Contains(name) && function.Name != name) {
try {
refDic[name.ToLower()].Add(function, module);
if (!function.MyFunctions.Contains(refDic[name.ToLower()])) {
function.MyFunctions.Add(refDic[name.ToLower()]);
}
} catch (Exception) {
Console.WriteLine(string.Format("Could not find a parent-module for {0} in {1}",name,function.Name));
}
}
}
}
}
Console.WriteLine("");
Console.WriteLine("======================");
Console.WriteLine("");
var shouldThrow = false;
foreach (var module in allModules.Where(x => !x.IsStub)) {
if (module.RelatedModules.Where(x => !x.IsStub).Any()) {
Console.WriteLine(string.Format("{0} uses",module.Name));
foreach (var subModule in module.RelatedModules.Where(x => !x.IsStub)) {
var isWrongOrder = (module.IsBase && !subModule.IsBase);
var isObviousCycle = subModule.RelatedModules.Contains(module);
if (isWrongOrder) {
Console.WriteLine(string.Format(" * {0} - WARNING - SOMETHING REQUIRES A HIGHER-ORDER-FUNCTION", subModule.Name));
var exceptions = subModule.ModuleFunctionDefinitions.Where(x => x.ReferencedBy.Where(y => y.Module == module).Any()).Select(x => new { Name = x.Name, Where = x.ReferencedBy.Where(t => t.Module == module).Select(t => t.Name).ToArray() });
foreach (var exception in exceptions) {
foreach (var functionName in exception.Where) {
Console.WriteLine(string.Format(" * !! {0} calls {1}",functionName,exception.Name));
}
}
shouldThrow = true;
} else if (isObviousCycle && showObviousCycles) {
Console.WriteLine(string.Format(" * {0} - WARNING - OBVIOUS CYCLE",subModule.Name));
var exceptions = subModule.ModuleFunctionDefinitions.Where(x => x.ReferencedBy.Where(y => y.Module == module).Any()).Select(x => new { Name = x.Name, Where = x.ReferencedBy.Where(t => t.Module == module).Select(t => t.Name).ToArray() });
foreach (var exception in exceptions) {
foreach (var functionName in exception.Where) {
Console.WriteLine(string.Format(" * !! {0} calls {1}",functionName,exception.Name));
}
}
shouldThrow = true;
} else {
Console.WriteLine(string.Format(" * {0}",subModule.Name));
}
}
} else {
Console.WriteLine(string.Format("{0} doesn't have additional-module usage",module.Name));
}
Console.WriteLine("");
}
return (shouldThrow);
}
}
public class ModuleDefinition {
public string Name { get; set; }
public List<ModuleFunctionDefinition> ModuleFunctionDefinitions { get; set; }
public List<ModuleDefinition> RelatedModules { get; set; }
public int Weight { get; set; }
public bool IsCsharp { get; set; }
/// <summary>
/// This flag means we are ignoring this "module" as it is only for comparison purposes
/// </summary>
public bool IsStub { get; set; }
/// <summary>
/// This means it's Alkami.PowerShell.* or something like it
/// </summary>
public bool IsBase { get; set; }
public ModuleDefinition() {
ModuleFunctionDefinitions = new List<ModuleFunctionDefinition>();
RelatedModules = new List<ModuleDefinition>();
Weight = 0;
}
public ModuleDefinition(string name) {
Name = name;
ModuleFunctionDefinitions = new List<ModuleFunctionDefinition>();
RelatedModules = new List<ModuleDefinition>();
Weight = 0;
IsBase = name.ToLower().StartsWith("Alkami.PowerShell".ToLower());
}
public ModuleDefinition(string name, IEnumerable<ModuleDefinition> relatedModuleNames) {
Name = name;
ModuleFunctionDefinitions = new List<ModuleFunctionDefinition>();
RelatedModules = new List<ModuleDefinition>();
RelatedModules.AddRange(relatedModuleNames);
Weight = 0;
IsBase = name.ToLower().StartsWith("Alkami.PowerShell".ToLower());
}
public ModuleDefinition AddFunction(ModuleFunctionDefinition functionDefinition) {
ModuleFunctionDefinitions.Add(functionDefinition);
return this;
}
public ModuleDefinition AddFunctions(IEnumerable<ModuleFunctionDefinition> functionDefinitions) {
ModuleFunctionDefinitions.AddRange(functionDefinitions);
return this;
}
public override bool Equals(Object obj) {
//Check for null and compare run-time types.
if ((obj == null) || !this.GetType().Equals(obj.GetType())) {
return false;
} else {
ModuleDefinition moduleDefinition = (ModuleDefinition)obj;
return Name == moduleDefinition.Name;
}
}
public override int GetHashCode() {
return Name.GetHashCode();
}
public override string ToString() {
return string.Format("ModuleDefintion: {0}",Name);
}
}
public class FunctionDefinition {
public string Name { get; set; }
public ModuleDefinition Module { get; set; }
public bool IsPrivate { get; set; }
public FunctionDefinition() {
}
public FunctionDefinition(string name) {
Name = name;
}
public FunctionDefinition(string name, ModuleDefinition module) {
Name = name;
Module = module;
}
public override bool Equals(Object obj) {
//Check for null and compare run-time types.
if ((obj == null) || !this.GetType().Equals(obj.GetType())) {
return false;
} else {
FunctionDefinition functionDefinition = (FunctionDefinition)obj;
return Name == functionDefinition.Name;
}
}
public override int GetHashCode() {
return Name.GetHashCode();
}
public override string ToString() {
return string.Format("ModuleFunctionDefinition: {0} - ModuleDefinition {1}",Name,Module.Name);
}
}
public class ModuleFunctionDefinition : FunctionDefinition {
public List<string> ReferencedFunctions { get; set; }
public ModuleFunctionDefinition() : this(null) { }
public ModuleFunctionDefinition(string name) : this(name, null) { }
public ModuleFunctionDefinition(string name, ModuleDefinition module) : this(name, module, null) { }
public ModuleFunctionDefinition(string name, ModuleDefinition module, IEnumerable<string> referencedFunctions) : base(name, module) {
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException("name");
if (module == null) throw new ArgumentNullException("module");
ReferencedFunctions = new List<string>();
if (referencedFunctions != null) {
ReferencedFunctions.AddRange(referencedFunctions);
}
ReferencedBy = new List<ModuleFunctionDefinition>();
ReferencedIn = new List<ModuleDefinition>();
MyFunctions = new List<FunctionDefinition>();
}
public FunctionDefinition Add(string referencedFunction) {
ReferencedFunctions.Add(referencedFunction);
return this;
}
public override bool Equals(Object obj) {
//Check for null and compare run-time types.
if ((obj == null) || !this.GetType().Equals(obj.GetType())) {
return false;
} else {
FunctionDefinition functionDefinition = (FunctionDefinition)obj;
return Name == functionDefinition.Name;
}
}
public override int GetHashCode() {
return Name.GetHashCode();
}
public override string ToString() {
return string.Format("ModuleFunctionDefinition: {0} - ModuleDefinition {1}",Name,Module.Name);
}
public void Add(ModuleFunctionDefinition functionDefinition, ModuleDefinition module) {
if (!ReferencedBy.Contains(functionDefinition)) { ReferencedBy.Add(functionDefinition); }
if (!ReferencedIn.Contains(module)) { ReferencedIn.Add(module); }
if (Module != module && !module.RelatedModules.Contains(Module)) { module.RelatedModules.Add(Module); }
}
// These are the functions that reference me
public List<ModuleFunctionDefinition> ReferencedBy { get; set; }
// These are the functions that I reference
public List<ModuleDefinition> ReferencedIn { get; set; }
public List<FunctionDefinition> MyFunctions { get; set; }
}
"@;
Write-Host "testing solution"
Add-Type -TypeDefinition $cSharpCode;
$result = [ModuleChecker]::DoIt($FolderPath, $ShowObviousCycles)
if ($result) {
if ($FailBuild) {
throw "Failed processing, check output for bad module definitions"
} else {
Write-Warning "Failed processing, check output for bad module definitions"
}
}
}