Private/Initialization.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
function Initialize-Nanite {
    # Create a global configuration.
    $Global:configuration = [PSCustomObject]@{
        Output = 'C:\Nanite'
        SessionRetentionDays = 14
        SupportedResources = @(
            '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'
        Return
    }

    # Check if there is a module update available by checking major and minor version numbers.
    # Build and revision numbers are ignored to allow incremental builds to be published and tested without flagging an update.
    $currentVersion = ((Get-Module -Name 'Nanite' | Select-Object Version).Version).ToString()
    $availableVersion = ((Find-Module -Name 'Nanite' -Repository 'PSGallery' | Select-Object Version).Version).ToString()
    If ([version]('{0}.{1}.{2}' -f $currentVersion.Split('.')) -lt [version]('{0}.{1}.{2}' -f $availableVersion.Split('.'))) {
        Write-Console -Message 'There is a new version of Nanite available by executing:' -Color 'Red'
        Write-Console -Message "Update-Module -Name 'Nanite'" -Color 'Red'
    }
    
    <#
    If ([version]$currentVersion -ne [version]$availableVersion) {
        Write-Console -Message 'There is a new version of Nanite available by executing:' -Color 'Red'
        Write-Console -Message "Update-Module -Name 'Nanite'" -Color 'Red'
    }#>


    # 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'
        Return
    }

    # Initialize the catalog.
    [System.Collections.ArrayList]$Global:operations = @()
    $operationsJSON = Invoke-Database -Query "SELECT [data] FROM [dbo].[operations]"
    ForEach ($operation in $operationsJSON.Tables.data) {
        $operation = $operation | ConvertFrom-Json
        $null = $Global:operations.Add($operation)
    }

    # 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."
}