432 lines
34 KiB
Plaintext
432 lines
34 KiB
Plaintext
|
<Query Kind="Program">
|
||
|
<Namespace>System.Collections</Namespace>
|
||
|
<Namespace>System.Collections.Generic</Namespace>
|
||
|
<Namespace>System.Linq</Namespace>
|
||
|
</Query>
|
||
|
|
||
|
|
||
|
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-ServiceConfigu
|
||
|
|
||
|
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 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<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($"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<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($"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<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 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<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($"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<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 $"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<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 $"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<ModuleFunctionDefinition> ReferencedBy { get; set; }
|
||
|
// These are the functions that I reference
|
||
|
public List<ModuleDefinition> ReferencedIn { get; set; }
|
||
|
|
||
|
public List<FunctionDefinition> MyFunctions { get; set; }
|
||
|
}
|