System.Collections System.Collections.Generic System.Linq public static class runner { public static string GetExecutingDirectory() { return @"z:\git\devops_powershell\"; //return Path.GetDirectoryName(Util.CurrentQueryPath); } static void Main() { ModuleChecker.DoIt(GetExecutingDirectory(), false); } } 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" }; /// /// Most of these fell out of comments because of the matching on verb-word /// 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 excludeNames = new List { "VariableDeclarations", "ConfigurationValues" }; const string CarbonModuleName = "Carbon"; const string WebAdministrationModuleName = "WebAdministration"; const string WindowsModuleName = "Generic Windows"; const string CloudbaseModuleName = "Cloudbase"; const string AwsModuleName = "AWS"; const string RedisModuleName = "Redis"; const string ServiceFabricModuleName = "ServiceFabric"; const string IgnoredFunctionsModuleName = "ignore anything with this module name"; #endregion static decls public static IEnumerable GetFunctionDefinitionsFromModule(DirectoryInfo directoryInfo, ModuleDefinition module, Regex regex) { var functionDefinitions = new List(); 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().SelectMany(m => m.Captures.OfType().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($"Did not match [{file.Name}] as a valid filename."); } } } } 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().SelectMany(m => m.Captures.OfType().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($"Did not match [{file.Name}] as a valid filename."); } } } } return functionDefinitions; } public static void DoIt(string searchPath, bool throwOnError) { var matchVerbsString = string.Join("|", verbs); var matchString = $"({matchVerbsString})-\\w+"; var regex = new Regex(matchString, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase); var allFoundFunctions = new List(); var allModules = new List(); #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 AWS 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 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 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 ignore records 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 ignore records for reference var modules = new DirectoryInfo(Path.Combine(searchPath, "Modules")).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($"Found a CS Project for {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 refDic = new Dictionary(); 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($"Could not find a parent-module for {name} in {function.Name}"); } } } } } Console.WriteLine(""); Console.WriteLine("======================"); Console.WriteLine(""); foreach (var module in allModules.Where(x => !x.IsStub)) { if (module.RelatedModules.Where(x => !x.IsStub).Any()) { Console.WriteLine($"{module.Name} uses"); 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($" * {subModule.Name} - WARNING - SOMETHING REQUIRES A HIGHER-ORDER-FUNCTION"); 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($" * !! {functionName} calls {exception.Name}"); } } } else if (isObviousCycle) { Console.WriteLine($" * {subModule.Name} - WARNING - OBVIOUS CYCLE"); } else { Console.WriteLine($" * {subModule.Name}"); } } } else { Console.WriteLine($"{module.Name} doesn't have additional-module usage"); } Console.WriteLine(""); } // SRE-13713 //carbon.ModuleFunctionDefinitions.Where(x => x.ReferencedBy.Any()).SelectMany(x => x.ReferencedBy.Select(r => r.Name)).Distinct().Dump(); } } public class ModuleDefinition { public string Name { get; set; } public List ModuleFunctionDefinitions { get; set; } public List RelatedModules { get; set; } public int Weight { get; set; } public bool IsCsharp { get; set; } /// /// This flag means we are ignoring this "module" as it is only for comparison purposes /// public bool IsStub { get; set; } /// /// This means it's Alkami.PowerShell.* or something like it /// public bool IsBase { get; set; } public ModuleDefinition() { ModuleFunctionDefinitions = new List(); RelatedModules = new List(); Weight = 0; } public ModuleDefinition(string name) { Name = name; ModuleFunctionDefinitions = new List(); RelatedModules = new List(); Weight = 0; IsBase = name.ToLower().StartsWith("Alkami.PowerShell".ToLower()); } public ModuleDefinition(string name, IEnumerable relatedModuleNames) { Name = name; ModuleFunctionDefinitions = new List(); RelatedModules = new List(); 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 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 $"ModuleDefintion: {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 $"FunctionDefinition: {Name} - ModuleDefinition {Module.Name}"; } } public class ModuleFunctionDefinition : FunctionDefinition { public List 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 referencedFunctions) : base(name, module) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException("name"); if (module == null) throw new ArgumentNullException("module"); ReferencedFunctions = new List(); if (referencedFunctions != null) { ReferencedFunctions.AddRange(referencedFunctions); } ReferencedBy = new List(); ReferencedIn = new List(); MyFunctions = new List(); } 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 $"ModuleFunctionDefinition: {Name} - ModuleDefinition {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 ReferencedBy { get; set; } // These are the functions that I reference public List ReferencedIn { get; set; } public List MyFunctions { get; set; } }