Private/Initialization.ps1

function Initialize-Nanite {
    # Create a global configuration.
    $Global:configuration = [PSCustomObject]@{
        AESKey = '\\arrserver.redmond.corp.microsoft.com\Public\Nanite\AES.key'
        Output = 'C:\Nanite'
        SessionRetentionDays = 14
        SupportedResources = @(
            'azureFirewalls',    
            'expressRouteCircuits'    
            'managedClusters',
            'netAppAccounts',
            'storageAccounts',
            'virtualMachines',
            'virtualMachineScaleSets'
        )
        Testing = 'C:\Nanite\Testing'
    }

    # Ensure that PowerShell is currently running as Administrator.
    If (!([bool]('S-1-5-32-544' -in ([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups))) {
        Write-Console -Message 'Please restart PowerShell as Administrator and then import Nanite.' -Color 'Red'
        Exit
    }

    # Attempt to locate the AES.key file.
    # The folder containing this key requires membership in the "Nanite Users" Security Group through Microsoft Identity Manager.
    If (!(Test-Path -Path $Global:configuration.AESKey -ErrorAction SilentlyContinue)) {
        Write-Console -Message 'The required key file could not be located.' -Color 'Red'
        Write-Console -Message "Make sure Nanite's core is up-to-date using `"Update-Module Nanite`" and try again." -Color 'Red'
        Exit
    }

    # Open a global database connection and ensure that the connection was made.
    $Global:database = Open-Database
    If (!($database)) {
        Write-Console -Message 'The database could not be reached.' -Color 'Red'
        Write-Console -Message "Make sure Nanite's core is up-to-date using `"Update-Module Nanite`" and try again." -Color 'Red'
        Exit
    }

    # Initialize the catalog.
    [System.Collections.ArrayList]$Global:operations = @()
    $operationsJSON = Invoke-Database -Query "SELECT [id], [data] FROM [dbo].[operations]"
    ForEach ($operation in $operationsJSON.Tables) {
        # Convert the JSON column into a PSCustomObject.
        $convertedOperation = $operation.data | ConvertFrom-Json
        # Add the operation's ID to the PSCustomObject.
        $convertedOperation | Add-Member -NotePropertyName 'id' -NotePropertyValue $operation.id
        $null = $Global:operations.Add($convertedOperation)
    }

    # Create the global session object.
    $Global:session = [PSCustomObject]@{}

    # Check if the root output directory exists and create it if not.
    If (!(Test-Path -Path $Global:configuration.Output)) {
        $NULL = New-Item -Path $Global:configuration.Output -ItemType Directory -Force
    }

    # Check if the temporary output directory exists and create it if not.
    # Clear out the temporary output directory if it already exists.
    If (!(Test-Path -Path "$($Global:configuration.Output)\Temporary")) {
        $NULL = New-Item -Path "$($Global:configuration.Output)\Temporary" -ItemType Directory -Force
    }
    Else {
        $files = Get-ChildItem -Path "$($Global:configuration.Output)\Temporary" -Recurse
        If ($files.Count -ne 0) {
            ForEach ($file in $files) {
                $file.FullName | Remove-Item -Force
            }
        }
    }

    # Check if the Session output directory exists and create it if not.
    # If the session output directory exists then clear out any sessions older than the $Global:configuration.SessionRetentionDays setting.
    # Session file removal is based on $_.LastWriteTime since $_.LastAccessTime isn't typically enabled in filesystems by default.
    If (!(Test-Path -Path "$($Global:configuration.Output)\Sessions")) {
        $NULL = New-Item -Path "$($Global:configuration.Output)\Sessions" -ItemType Directory -Force
    }
    Else {
        $files = Get-ChildItem -Path "$($Global:configuration.Output)\Sessions" -Recurse
        $lookback = (Get-Date).AddDays(-$($Global:configuration.SessionRetentionDays))
        If ($files.Count -ne 0) {
            ForEach ($file in $files) {
                If ($lookback -gt $file.LastWriteTime) {
                    $file.FullName | Remove-Item -Force
                }
            }
        }
    }

    # Check for an installation of the Kusto package and install it if not present.
    $kustoInstallation = Get-Package -Name 'Microsoft.Azure.Kusto.Tools' -ErrorAction SilentlyContinue
    If (!($kustoInstallation)) {
        Write-Console -Message 'Kusto libraries were not found locally; attempting installation...'
        # We are deregistering the package source to reregister it as a trusted source.
        If (Get-PackageSource -ProviderName NuGet -WarningAction SilentlyContinue) {
            Unregister-PackageSource -Name NuGet
        }
        $NULL = Register-PackageSource -Name NuGet -Location 'https://www.nuget.org/api/v2' -ProviderName NuGet -Trusted
        $NULL = Install-Package -Name 'Microsoft.Azure.Kusto.Tools' -Source 'NuGet'
    }
    
    # Load the Kusto package.
    $kustoInstallation = Get-Package -Name 'Microsoft.Azure.Kusto.Tools' -ErrorAction SilentlyContinue
    $kustoPath = ($kustoInstallation.Source).Substring(0, ($kustoInstallation.Source).lastIndexOf('\'))
    dir "$kustoPath\*" | Unblock-File
    $NULL = [System.Reflection.Assembly]::LoadFrom("$kustoPath\tools\Kusto.Data.dll")
    If (!([System.AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.Location -like '*Kusto.Data.dll' })) {
        Write-Console -Message 'Failed to load Kusto dependencies.' -Color 'Red'
        Exit
    }

    # Welcome.
    Write-Console -Message "Welcome to Nanite, $($ENV:USERNAME.ToUpper())!" -Color 'Green'
    Write-Console -Message "The catalog contains $($operations.Count) operations."
}