lib/ReferenceDesigns.ps1
function Get-TMReferenceDesign { <# .SYNOPSIS Gets/Downloads a Reference Design from the TDS BitBucket tm-reference-designs repo .DESCRIPTION This function .PARAMETER Name The name of the Reference Design to download .PARAMETER Credential The credentials used to log into BitBucket .PARAMETER SkipDependencies Switch indicating that the Reference Designs on which the named Reference Design depends on should not be downloaded .PARAMETER ManifestUri The uri of the raw rd-manifest.json. Defaults to the file in the __Releases directory .PARAMETER Dev Switch indicating that all reference designs should be searched/retrieved rather than just the published ones .PARAMETER ProviderName One or more specific Providers to get. All other Providers will be removed from the downloaded Reference Design .EXAMPLE $Credential = Get-StoredCredential -Name 'ME' Get-TMReferenceDesign -Name 'vmware-vcenter' -Credential $Credential -Dev .OUTPUTS None #> [CmdletBinding(DefaultParameterSetName = 'Console')] param ( [Parameter(Mandatory = $false, Position = 0, ParameterSetName = 'Console')] [String[]]$Name, [Parameter(Mandatory = $false, Position = 1)] [PSCredential]$Credential, [Parameter(Mandatory = $false)] [Switch]$SkipDependencies, [Parameter(Mandatory = $false)] [String]$ManifestUri, [Parameter(Mandatory = $false)] [Switch]$Dev, [Parameter(Mandatory = $false)] [String[]]$ProviderName # [Parameter(Mandatory = $false, ParameterSetName = "UI")] # [Switch]$ShowMenu # TODO: Consider if we could add a $Path/$Location type # parameter to allow the user to specify a filesystem ) # Some of the TMD functions will be needed in this function if (!( Get-Module 'TMD.Common')) { Import-Module 'TMD.Common' } ## Create a $PackageNames variable with all of the Reference Design names (Lower, no spaces) $PackageNames = $Name.ToLower() -replace ' - ', '-' -replace ' ', '-' ## Save the Progress Preference now so that it can be changed and set back later $ProgressPreferenceBackup = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' $RDFolder = Join-Path $Global:userFilesRoot 'Reference Designs' $LocalReferenceDesigns = [System.Collections.ArrayList]::new() $ReferenceDesignsToDownload = [System.Collections.ArrayList]::new() # $ShouldInstall = $false ## TODO: I don't like this credential handling. If a user supplies a credential, it should not be written to disk, but only used. ## To mitigate this, you could do a few things -StoreCredentialAs (Name), or ## -CredentialName {Which would hand off to Get-StoredCredential} # Check if the credential is already cached $CredentialPath = Join-Path -Path $Global:UserPaths.credentials -ChildPath 'Bitbucket.credential' if (!$Credential) { $Credential = (Test-Path -Path $CredentialPath) ? (Get-StoredCredential -Name 'Bitbucket') : (Get-Credential) } # Save the credential for future use Add-StoredCredential -Name 'Bitbucket' -Credential $Credential Write-Verbose 'Credential was stored as Bitbucket.credential' # Get the reference design manifest from bitbucket Write-Host 'Getting available Reference Designs from Bitbucket...' try { if ([String]::IsNullOrWhiteSpace($ManifestUri)) { $ManifestUri = "https://git.tdsops.com/projects/TM/repos/tm-reference-designs/raw/__Releases/$(if ($Dev) {'dev-'})rd-manifest.json?at=refs%2Fheads%2Fmain" } $AvailableReferenceDesigns = Invoke-RestMethod -Method Get -Uri $ManifestUri -Authentication Basic -Credential $Credential } catch { throw "Couldn't get the manifest file. Check credentials and try again" } Write-Host "`tFound " -NoNewline Write-Host "$($AvailableReferenceDesigns.Count)" -NoNewline -ForegroundColor DarkBlue Write-Host ' available Reference Design(s)' # Fix the version so that it can be compared later in the script for ($i = 0; $i -lt $AvailableReferenceDesigns.Count; $i++) { $AvailableReferenceDesigns[$i].Version = ConvertTo-SemanticVersion -VersionString $AvailableReferenceDesigns[$i].Version for ($j = 0; $j -lt $AvailableReferenceDesigns[$i].referenceDesign.dependencies.referenceDesigns.Count; $j++) { $AvailableReferenceDesigns[$i].referenceDesign.dependencies.referenceDesigns[$j].version = ConvertTo-SemanticVersion -VersionString $AvailableReferenceDesigns[$i].referenceDesign.dependencies.referenceDesigns[$j].version } } # Either show the UI to get the user's selections or switch ($PSCmdlet.ParameterSetName) { 'Console' { Write-Verbose 'Console mode was selected' # If no name was supplied, just output the RD objects if (!$PackageNames) { $AvailableReferenceDesigns | ForEach-Object { $_ } return } else { $PackageNames | ForEach-Object { $RD = $AvailableReferenceDesigns | Where-Object name -EQ $_ | Sort-Object -Property version | Select-Object -Last 1 if ($RD) { [void]$ReferenceDesignsToDownload.Add($RD) } } } } <# "UI" { Write-Verbose "UI mode was selected" # $ExePath = "..\exe\RD Installer.exe" $ExePath = "C:\DEV\git\tm-reference-designs\_ReferenceDesignManager\ReferenceDesignManager\bin\Debug\net5.0-windows\ReferenceDesignManager.exe" $StartInfo = [System.Diagnostics.ProcessStartInfo]::new() $StartInfo.RedirectStandardError = $true $StartInfo.RedirectStandardOutput = $true $StartInfo.FileName = $ExePath # $StartInfo.ArgumentList = @( # "--repocredential `"$CredentialPath`"" # "--powershell" # ) $StartInfo.Arguments = "--repocredential `"$CredentialPath`" --powershell" $RDInstallerProc = [System.Diagnostics.Process]::new() $RDInstallerProc.StartInfo = $StartInfo # Start the UI and wait for it to exit so that the stdout can be parsed Write-Host "Showing UI..." $RDInstallerProc.Start() $RDInstallerProc.WaitForExit() $StdOut = $RDInstallerProc.StandardOutput.ReadToEnd() if ([String]::IsNullOrWhiteSpace($StdOut)) { throw "Output was not received from $(Split-Path $ExePath -Leaf)" } $UserChoices = $StdOut | ConvertFrom-Json $UserChoices.ReferenceDesignsToDownload | ForEach-Object { [void]$ReferenceDesignsToDownload.Add( @{ Name = $_ Version = $null } ) } $ShouldInstall = $UserChoices.ShouldInstall } #> } # Make sure one or more available Reference Designs were found if ($ReferenceDesignsToDownload.Count -eq 0) { throw "No available Reference Designs were found with the specified name(s): $($PackageNames.ToString())" } ## Create the Destination Downloaded Folder $DownloadedFolder = Join-Path $RDFolder 'Downloaded' Test-FolderPath $DownloadedFolder # Get all of the Reference Designs that are already downloaded Write-Host 'Checking for downloaded Reference Designs...' Write-Verbose "Looking in '$DownloadFolder'" try { Get-ChildItem -Path $DownloadedFolder -Filter 'package.json' -Recurse | Get-Content -Raw | ConvertFrom-Json | ForEach-Object { [void]$LocalReferenceDesigns.Add($_) } } catch { Write-Verbose $_ } Write-Host "`tFound " -NoNewline Write-Host "$($LocalReferenceDesigns.Count)" -NoNewline -ForegroundColor DarkBlue Write-Host ' local Reference Design(s)' # Check if the selected Reference Designs have any dependencies on other Reference Designs if (!$SkipDependencies) { Write-Host 'Checking for Reference Design dependencies...' $Count = $ReferenceDesignsToDownload.Count for ($i = 0; $i -lt $Count; $i++) { $Design = $ReferenceDesignsToDownload[$i] foreach ($Dependency in $Design.referenceDesign.dependencies.referenceDesigns) { $AvailableRD = $AvailableReferenceDesigns | Where-Object Name -EQ $Dependency.name | Sort-Object -Property version | Select-Object -Last 1 if ($AvailableRD) { $LocalRD = $LocalReferenceDesigns | Where-Object Name -EQ $Dependency.name | Sort-Object -Property version | Select-Object -Last 1 if ($LocalRD) { if ($LocalRD.version -lt $Dependency.version) { Write-Host "`tFound Reference Design to update: " -NoNewline Write-Host "$($AvailableRD.Name) - v$($AvailableRD.Version.ToString())" [void]$ReferenceDesignsToDownload.Add($AvailableRD) } } else { Write-Host "`tFound additional Reference Design to download: " -NoNewline Write-Host "$($AvailableRD.Name) - v$($AvailableRD.Version.ToString())" [void]$ReferenceDesignsToDownload.Add($AvailableRD) } } } } } # Start downloading the named reference designs Write-Host 'Downloading Reference Designs...' # $EncounteredError = $false foreach ($RDSpec in $ReferenceDesignsToDownload) { Write-Host "`tProcessing: " -NoNewline Write-Host $RDSpec.ProductName -ForegroundColor DarkBlue ## Resolve the file name and the destination path $ZipFileName = $RDSpec.Name + '-' + $RDSpec.Version + '.zip' $Url = 'https://git.tdsops.com/projects/TM/repos/tm-reference-designs/raw/__Releases/{0}?at=refs%2Fheads%2Fmain' -f $ZipFileName $DestinationFilePath = Join-Path $RDFolder 'Downloaded' $ZipFileName try { ## Call to Bitbucket to download the file Write-Host "`t`tDownloading $ZipFileName ($([Math]::Round(($RDSpec.Size / 1MB), 2)) MB)..." -NoNewline Invoke-WebRequest -Uri $Url -Credential $Credential -Authentication Basic -Method Get -OutFile $DestinationFilePath Write-Host 'Done' -ForegroundColor Green } catch { Write-Error $_ continue } try { # Unzip the downloaded file Write-Host "`t`tExpanding archive..." -NoNewline $DestinationDirectory = Join-Path $RDFolder 'Downloaded' $RDSpec.ProductName Expand-Archive -Path $DestinationFilePath -DestinationPath $DestinationDirectory -Force Write-Host 'Done' -ForegroundColor DarkGreen } catch { Write-Error $_ continue } # Remove the .zip file now that its contents been extracted Remove-Item -Path $DestinationFilePath -Force if ($PSBoundParameters.ContainsKey('ProviderName')) { # Remove the actions and ETL scripts that don't belong to the specified providers $ScriptPaths = @( (Join-Path $DestinationDirectory '_REFERENCE DESIGN' 'Actions') (Join-Path $DestinationDirectory '_REFERENCE DESIGN' 'ETL') ) Get-ChildItem -Path $ScriptPaths -Directory -Exclude $ProviderName | Remove-Item -Recurse -Force # Remove the providers from providers.json that weren't specified in ProviderName $FilteredProviders = [System.Collections.ArrayList]::new() $ProviderFile = Join-Path $DestinationDirectory '_REFERENCE DESIGN' 'Providers.json' $Providers = , @(Get-Content -Path $ProviderFile | ConvertFrom-Json -Depth 10) foreach ($Provider in $Providers) { if ($Provider.name -in $ProviderName) { [void]($FilteredProviders.Add($Provider)) } } ConvertTo-Json -Depth 10 -InputObject $FilteredProviders | Set-Content -Path $ProviderFile -Force } } ## Set the progress preference back $Global:ProgressPreference = $ProgressPreferenceBackup # if ($ShouldInstall -and !$EncounteredError) { # Install-TMReferenceDesign -Name $UserChoices.ReferenceDesignsToDownload # } } function Get-TMLocalReferenceDesign { <# .SYNOPSIS Gets one or more Reference Designs that have been downloaded loacally .DESCRIPTION This function scans the C:\Users\<user>\TMD_Files\Reference Designs directory for the package.json file(s) associated with Reference Designs that have been downloaded locally .PARAMETER Name The name(s) of the downloaded Reference Design(s) to retrieve .PARAMETER List Switch indicating that only a list of downloaded Reference Design names should be returned .EXAMPLE Get-TMLocalReferenceDesign -Name 'vmware-vcenter', 'vmware-hcx' .EXAMPLE Get-TMLocalReferenceDesign -List .OUTPUTS An array of strings representing the downloaded Reference Design names if the -List switch is used otherwise a PSCustomObject for each name that was passed #> [CmdletBinding(DefaultParameterSetName = 'Named')] [OutputType([PSCustomObject[]], ParameterSetName = 'Named')] [OutputType([String[]], ParameterSetName = 'List')] param ( [Parameter( Mandatory = $false, ParameterSetName = 'Named', ValueFromPipeline = $true)] [String[]]$Name, [Parameter(Mandatory = $false, ParameterSetName = 'List')] [Switch]$List ) begin { if (!(Get-Module 'TMD.Common')) { Import-Module 'TMD.Common' } $RDDirectory = Join-Path $Global:userFilesRoot 'Reference Designs' $LocalReferenceDesigns = Get-ChildItem -Path $RDDirectory -Filter 'package.json' -Recurse -Force | ForEach-Object { $Package = Get-Content -Path $_.FullName -Raw | ConvertFrom-Json -Depth 100 Add-Member -InputObject $Package -Name 'path' -Value (Split-Path $_.FullName) -MemberType NoteProperty -PassThru } } process { if ($List) { $LocalReferenceDesigns | ForEach-Object { $_.Name } } else { if ($Name) { $Name | ForEach-Object { $LocalReferenceDesigns | Where-Object Name -EQ $_ } } else { $LocalReferenceDesigns } } } } function Import-TMReferenceDesign { <# .SYNOPSIS Imports a downloaded Reference Design to the specified project on the specified server .DESCRIPTION This function will apply the different configuration components of a Reference Design into a TransitonManager project. .PARAMETER Name The name of the locally downloaded Reference Design to apply/install .PARAMETER TMSession The name of the TM Session to use when creating a Team .PARAMETER Project The project in which the Reference Design will be applied .PARAMETER Exclude An array of components to skip when performing the import. Options are: DependencyTypes FieldSpecs Bundles Providers Actions ETLScripts Recipes Tags AssetViews Events AppTypes DeviceTypes Teams TaskCategories SetupScripts .PARAMETER SkipDependencies Switch indicating that the Reference Designs on which the named Reference Design depends on should not be imported .PARAMETER ProviderName One or more specific Providers to import. All other Providers will not be imported into the project .EXAMPLE $Credential = Get-StoredCredential -Name 'ME' $ImportSplat = @{ Name = 'vmware-vcenter' Project = 'New Project - VMware vCenter' TMSession = 'TMAD60' } Import-TMReferenceDesign @ImportSplat .OUTPUTS None #> param ( [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ArgumentCompleter( { Get-TMLocalReferenceDesign -List } )] [String[]]$Name, [Parameter(Mandatory = $false, Position = 1)] [String]$TMSession = "Default", [Parameter(Mandatory = $true, Position = 2)] [String]$Project, [Parameter(Mandatory = $false, Position = 4)] [ValidateSet( 'DependencyTypes', 'FieldSpecs', 'Bundles', 'Providers', 'Actions', 'ETLScripts', 'Recipes', 'Tags', 'AssetViews', 'Events', 'AppTypes', 'DeviceTypes', 'Teams', 'TaskCategories', 'SetupScripts' )] [String[]]$Exclude, [Parameter(Mandatory = $false)] [Switch]$SkipDependencies, [Parameter(Mandatory = $false)] [String[]]$ProviderName ) begin { # Get the session configuration Write-Verbose "Checking for cached TMSession" $TMSessionConfig = $global:TMSessions[$TMSession] Write-Debug "TMSessionConfig:" Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5) if (-not $TMSessionConfig) { throw "TMSession '$TMSession' not found. Use New-TMSession command before using features." } if (!(Get-Module 'TMD.Common')) { Import-Module 'TMD.Common' } $FilterByProvider = $PSBoundParameters.ContainsKey('ProviderName') ## Tag Color Map ## PowerShell Colors: ## Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White ## TM Tag Colors: ## 'Grey', 'Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Cyan', 'Purple', 'Pink', 'White' $TagColorToForeground = @{ 'Grey' = 'DarkGray' 'Red' = 'Red' 'Orange' = 'DarkYellow' 'Yellow' = 'Yellow' 'Green' = 'Green' 'Blue' = 'Blue' 'Cyan' = 'Cyan' 'Purple' = 'DarkMagenta' 'Pink' = 'Magenta' 'White' = 'White' } # Set up a configuration object to determine which components to install later in the process block $Components = @{ DependencyTypes = $true FieldSpecs = $true Bundles = $true Providers = $true Actions = $true ETLScripts = $true Recipes = $true Tags = $true AssetViews = $true Events = $true AppTypes = $true DeviceTypes = $true Teams = $true TaskCategories = $true SetupScripts = $true } # Process the Exclude parameter and turn components off $Exclude | ForEach-Object { $Components.$_ = $false } # Get a list of all of the Reference Designs that have been saved locally $RDDirectory = Join-Path $Global:userFilesRoot 'Reference Designs' $LocalReferenceDesigns = Get-TMLocalReferenceDesign if (!$LocalReferenceDesigns) { throw "No locally saved reference designs were found in $RDDirectory. Use Get-TMReferenceDesign to download before installing." } if ($TMSessionConfig.userContext.project.name -ne $Project) { ## The user is in the wrong project, change to the correct one. Enter-TMProject -ProjectName $Project -TMSession $TMSession } } process { # Get the RD spec from the passed Names and verify they are already downloaded $RDToInstall = @() foreach ($RDName in $Name) { $RDName = $RDName.ToLower().Replace(' - ', '-').Replace(' ', '-') $RD = $LocalReferenceDesigns | Where-Object Name -EQ $RDName if (!$RD) { throw "The reference design $RDName has not been downloaded locally. Use Get-TMReferenceDesign and try again." } $RDToInstall += $RD if (!$SkipDependencies) { # Resolve any dependencies ## Remove Placeholder tokens provided by the template file creation $DependentRds = $RD.referenceDesign.dependencies.referenceDesigns | Where-Object { $_.name -ne '<PLACEHOLDER>' } foreach ($DependencyItem in $DependentRds) { $Dependency = $LocalReferenceDesigns | Where-Object { $_.Name -eq $DependencyItem.Name -and $_.Version -eq $DependencyItem.Version } if (!$Dependency) { throw "The dependency Reference Design $($DependencyItem.Name) (v$($DependencyItem.Version)) was not found on the local hard drive. Use Get-TMReferenceDesign and try again." } $RDToInstall += $Dependency } } } ## Create an array of Setup Scripts to run $SetupScriptsToRun = [System.Collections.ArrayList]@() ## Iterate over each Reference Design to Install foreach ($RD in $RDToInstall) { Write-Host 'Importing: ' -NoNewline Write-Host $Rd.productName -NoNewline -ForegroundColor Cyan Write-Host ", Version: " -NoNewline Write-Host $Rd.Version -ForegroundColor DarkGray # $ReferenceDesignPath = $RD.Path $ReferenceDesignPath = Join-Path $RD.Path '_REFERENCE DESIGN' # Create the dependency types if ($Components.DependencyTypes) { Write-Host 'Loading Dependency Types...' $DependencyTypesFilePath = Join-Path $ReferenceDesignPath 'DependencyTypes.json' if (!(Test-Path $DependencyTypesFilePath)) { Write-Host "`tNo Dependency Types to add" } else { ## Get the Server's existing Dependency Types $ServerDependencyTypes = Get-TMDependencyType -TMSession $TMSession $DependencyTypes = Get-Content -Path $DependencyTypesFilePath | ConvertFrom-Json foreach ($DependencyType in $DependencyTypes) { ## If the server doesn't have the dependency type if ($ServerDependencyTypes.label -notcontains $DependencyType.label) { ## Add it to the server Write-Host "`tLoading Dependency Type: " -NoNewline Write-Host "$($DependencyType.label)" -ForegroundColor DarkBlue $DependencyType = [TMDependencyType]::new($DependencyType.label) New-TMDependencyType -DependencyType $DependencyType.label -TMSession $TMSession } } } } # Create the App types if ($Components.AppTypes) { Write-Host 'Loading App Types...' $AppTypesFilePath = Join-Path $ReferenceDesignPath 'AppTypes.json' if (!(Test-Path $AppTypesFilePath)) { Write-Host "`tNo App Types to add" } else { ## Get the Server's existing App Types $ServerAppTypes = Get-TMAssetOption -Type 'App Type' -TMSession $TMSession $AppTypes = Get-Content -Path $AppTypesFilePath | ConvertFrom-Json foreach ($AppType in $AppTypes) { ## If the server doesn't have the App type if ($ServerAppTypes.label -notcontains $AppType.label) { ## Add it to the server Write-Host "`tLoading App Type: " -NoNewline Write-Host "$($AppType.label)" -ForegroundColor DarkBlue $AppType = [TMAppType]::new($AppType.label) New-TMAssetOption -Type 'App Type' -Name $AppType.label -TMSession $TMSession } } } } # Create the Device types if ($Components.DeviceTypes) { Write-Host 'Loading Device Types...' $DeviceTypesFilePath = Join-Path $ReferenceDesignPath 'DeviceTypes.json' if (!(Test-Path $DeviceTypesFilePath)) { Write-Host "`tNo Device Types to add" } else { ## Get the Server's existing Device Types $ServerDeviceTypes = Get-TMAssetOption -Type 'Asset Type' -TMSession $TMSession $DeviceTypes = Get-Content -Path $DeviceTypesFilePath | ConvertFrom-Json foreach ($DeviceType in $DeviceTypes) { ## If the server doesn't have the Device type if ($ServerDeviceTypes.label -notcontains $DeviceType.label) { ## Add it to the server Write-Host "`tLoading Device Type: " -NoNewline Write-Host "$($DeviceType.label)" -ForegroundColor DarkBlue $DeviceType = [TMAssetType]::new($DeviceType.label) New-TMAssetOption -Type 'Asset Type' -Name $DeviceType.label -TMSession $TMSession } } } } # Create the Task Categories if ($Components.TaskCategories) { Write-Host 'Loading Task Categories...' $TaskCategoriesFilePath = Join-Path $ReferenceDesignPath 'TaskCategories.json' if (!(Test-Path $TaskCategoriesFilePath)) { Write-Host "`tNo Task Categories to add" } else { ## Get the Server's existing Task Categories $ServerTaskCategories = Get-TMAssetOption -Type 'Task Category' -TMSession $TMSession $TaskCategories = Get-Content -Path $TaskCategoriesFilePath | ConvertFrom-Json foreach ($TaskCategory in $TaskCategories) { ## If the server doesn't have the Device type if ($ServerTaskCategories.label -notcontains $TaskCategory.label) { ## Add it to the server Write-Host "`tLoading Task Category: " -NoNewline Write-Host "$($TaskCategory.label)" -ForegroundColor DarkBlue $TaskCategory = [TMTaskCategory]::new($TaskCategory.label) New-TMAssetOption -Type 'Task Category' -Name $TaskCategory.label -TMSession $TMSession } } } } # Load the Field Specs if ($Components.FieldSpecs) { Write-Host 'Loading Field Specs...' $FieldSpecsFilePath = Join-Path $ReferenceDesignPath 'FieldSpecs.json' if (!(Test-Path $FieldSpecsFilePath)) { Write-Host "`tNo Asset Field Specs to add" } else { $FieldSpecs = Get-Content -Path $FieldSpecsFilePath | ConvertFrom-Json 'APPLICATION', 'DEVICE', 'DATABASE', 'STORAGE' | ForEach-Object { $DomainColor = switch ($_) { 'APPLICATION' { 'DarkMagenta' } 'DEVICE' { 'DarkCyan' } 'DATABASE' { 'DarkYellow' } 'STORAGE' { 'DarkGreen' } } foreach ($Field in $FieldSpecs.$_.fields) { Write-Host "`tLoading Field Spec: [" -NoNewline Write-Host "$_" -ForegroundColor $DomainColor -NoNewline Write-Host '] ' -NoNewline Write-Host "$($Field.label)" -ForegroundColor DarkBlue } } Update-TMFieldSpecs -FieldSpecs $FieldSpecs -TMSession $TMSession } } # Load the Bundles if ($Components.Bundles) { Write-Host 'Loading Bundles...' $BundlesFilePath = Join-Path $ReferenceDesignPath 'Bundles.json' if (!(Test-Path $BundlesFilePath)) { Write-Host "`tNo Bundles to add" } else { $Bundles = Get-Content -Path $BundlesFilePath | ConvertFrom-Json foreach ($Bundle in $Bundles) { Write-Host "`tLoading Bundle: " -NoNewline Write-Host "$($Bundle.Name)" -ForegroundColor DarkBlue New-TMBundle -Bundle $Bundle -TMSession $TMSession } } } # Load the Events if ($Components.Events) { Write-Host 'Loading Events...' $EventsFilePath = Join-Path $ReferenceDesignPath 'Events.json' if (!(Test-Path $EventsFilePath)) { Write-Host "`tNo Events to add" } else { $Events = Get-Content -Path $EventsFilePath | ConvertFrom-Json foreach ($TMEvent in $Events) { Write-Host "`tLoading Event: " -NoNewline Write-Host "$($Event.Name)" -ForegroundColor DarkBlue New-TMEvent $TMEvent -TMSession $TMSession } } } # Load the Teams if ($Components.Teams) { Write-Host 'Loading Teams...' $TeamsFilePath = Join-Path $ReferenceDesignPath 'Teams.json' if (!(Test-Path $TeamsFilePath)) { Write-Host "`tNo Teams to add" } else { $Teams = Get-Content -Path $TeamsFilePath | ConvertFrom-Json foreach ($Team in $Teams) { Write-Host "`tLoading Team: " -NoNewline Write-Host "$($Team.Code)" -ForegroundColor DarkBlue New-TMTeam -Code $Team.Code -Description $Team.Description -Level $Team.Level -Help $Team.Help -TMSession $TMSession } } } # Load the Providers if ($Components.Providers) { Write-Host 'Loading Providers...' $ProvidersFilePath = Join-Path $ReferenceDesignPath 'Providers.json' if (-Not (Test-Path $ProvidersFilePath)) { Write-Host "`tNo Providers to add" } else { $Providers = Get-Content -Path $ProvidersFilePath | ConvertFrom-Json foreach ($Provider in $Providers) { if ($FilterByProvider -and ($Provider.Name -notin $ProviderName)) { continue } Write-Host "`tLoading Provider: " -NoNewline Write-Host "$($Provider.Name)" -ForegroundColor DarkBlue New-TMProvider -Provider $Provider -TMSession $TMSession } } } # Load Actions if ($Components.Actions) { Write-Host 'Loading Actions...' if ($FilterByProvider) { $ActionsFolderPath = Get-ChildItem -Path (Join-Path $ReferenceDesignPath 'Actions') -Directory | Where-Object { $_.Name -in $ProviderName } } else { $ActionsFolderPath = Join-Path $ReferenceDesignPath 'Actions' } if (-Not (Test-Path $ActionsFolderPath)) { Write-Host "`tNo Actions to add" } else { # TODO: Is the 'Private' folder supposed to be excluded? $ActionFiles = Get-ChildItem -Path $ActionsFolderPath -Recurse -File | Where-Object { $_.Extension -eq '.ps1' } foreach ($ActionFile in $ActionFiles) { $Action = Read-TMActionScriptFile -Path $ActionFile Write-Host "`tLoading Action: " -NoNewline Write-Host "$($Action.Name)" -ForegroundColor DarkBlue New-TMAction -Action $Action -Update -TMSession $TMSession } } } # ETL Scripts if ($Components.ETLScripts) { Write-Host 'Loading ETL Scripts...' if ($FilterByProvider) { $ETLScriptFolderPath = Get-ChildItem -Path (Join-Path $ReferenceDesignPath 'ETL') -Directory | Where-Object { $_.Name -in $ProviderName } } else { $ETLScriptFolderPath = Join-Path $ReferenceDesignPath 'ETL' } if (-Not (Test-Path $ETLScriptFolderPath)) { Write-Host "`tNo ETL Scripts to add" } else { ## Get the Recipe files from the Recipe folder $ETLScriptFiles = Get-ChildItem -Path $ETLScriptFolderPath -Recurse -File | Where-Object { $_.Extension -eq '.groovy' } foreach ($ETLScriptFile in $ETLScriptFiles) { $ETLScript = Read-TMETLScriptFile -Path $ETLScriptFile Write-Host "`tLoading ETL Script: " -NoNewline Write-Host "$($ETLScript.Name)" -ForegroundColor DarkBlue New-TMETLScript -ETLScript $ETLScript -Update -TMSession $TMSession } } } # Recipes if ($Components.Recipes) { Write-Host 'Loading Recipes...' $RecipesFolderPath = Join-Path $ReferenceDesignPath 'Recipes' if (-Not (Test-Path $RecipesFolderPath)) { Write-Host "`tNo Recipes to add" } else { $RecipeFiles = Get-ChildItem -Path $RecipesFolderPath -File | Where-Object { $_.Extension -eq '.groovy' } foreach ($RecipeFile in $RecipeFiles) { $Recipe = Read-TMRecipeScriptFile -Path $RecipeFile Write-Host "`tLoading Recipe: " -NoNewline Write-Host "$($Recipe.Name)" -ForegroundColor DarkBlue New-TMRecipe -Recipe $Recipe -Update -TMSession $TMSession } } } # Load the Tags if ($Components.Tags) { Write-Host 'Loading Tags...' $TagsFilePath = Join-Path $ReferenceDesignPath 'Tags.json' if (-Not (Test-Path $TagsFilePath)) { Write-Host "`tNo Tags to add" } else { $Tags = Get-Content -Path $TagsFilePath | ConvertFrom-Json foreach ($Tag in $Tags) { Write-Host "`tLoading Tag: " -NoNewline Write-Host "$($Tag.Name)" -ForegroundColor $TagColorToForeground.($Tag.Color) New-TMTag -Name $Tag.Name -Description $Tag.description -Color $Tag.color -TMSession $TMSession } } } # Load the AssetViews if ($Components.AssetViews) { Write-Host 'Loading AssetViews...' $AssetViewsFilePath = Join-Path $ReferenceDesignPath 'AssetViews.json' if (-Not (Test-Path $AssetViewsFilePath)) { Write-Host "`tNo AssetViews to add" } else { $AssetViews = Get-Content -Path $AssetViewsFilePath | ConvertFrom-Json foreach ($AssetView in $AssetViews) { Write-Host "`tLoading AssetView: " -NoNewline Write-Host "$($AssetView.Name)" -ForegroundColor DarkBlue New-TMAssetViewConfiguration $AssetView -TMSession $TMSession } } } # SetupScripts if ($Components.SetupScripts) { Write-Host 'Collecting Setup Scripts...' $SetupScriptsFolderPath = Join-Path $ReferenceDesignPath '_SETUP' if (-Not (Test-Path $SetupScriptsFolderPath)) { Write-Host "`tNo Setup Scripts to run" } else { $SetupScriptFiles = Get-ChildItem -Path $SetupScriptsFolderPath -File | Where-Object { $_.Extension -eq '.ps1' } foreach ($SetupScriptFile in $SetupScriptFiles) { Write-Host "`Queuing Setup Script: " -NoNewline Write-Host "$($SetupScriptFile.Name)" -ForegroundColor DarkBlue [void]$SetupScriptsToRun.Add($SetupScriptFile) } } } } ## Sort the Setup Scripts to run by name $SortedSetupScripts = $SetupScriptsToRun | Sort-Object -Property 'Name' ## Iterate over each setup script and run them each foreach ($SetupScript in $SortedSetupScripts) { Write-Host "`tRunning Setup Script: " -NoNewline Write-Host "$($SetupScript.Name)" -ForegroundColor DarkBlue ## Try the script try { & "$($SetupScript.FullName)" } catch { Write-Host 'Setup Script Failed!' Write-Error $_ } } } } function Export-TMReferenceDesign { <# .SYNOPSIS Exports a TransitionManager project into a portable configuration package that can be applied in a different project and/or on a different server .DESCRIPTION This function will retreieve the different configuration components from a TransitonManager project and save them locally in a standardized format that can then be used to import those configurations on another TM project or TM instance. .PARAMETER Name What the Reference Design will be named .PARAMETER TMSession The name of the TM Session to use when creating a Team .PARAMETER Project The project that will be exported .PARAMETER Exclude An array of components to skip when performing the export. Options are: DependencyTypes FieldSpecs Bundles Providers Actions ETLScripts Recipes AssetViews Events AppTypes DeviceTypes Teams TaskCategories .PARAMETER OutPath The directory where the Reference Design will be saved .EXAMPLE $Credential = Get-StoredCredential -Name 'ME' $ExportSplat = @{ Name = 'VMWare - vCenter' Server = 'tmddev.transitionmanager.net' Project = 'RD - VMware vCenter' Credential = $Credential } Export-TMReferenceDesign @ExportSplat .OUTPUTS None #> [CmdletBinding()] param ( [Parameter(Mandatory = $false, Position = 0)] [String]$Name, [Parameter(Mandatory = $false, Position = 1)] [String]$TMSession = "Default", [Parameter(Mandatory = $false, Position = 2)] [String]$Project, [Parameter(Mandatory = $false, Position = 3)] [ValidateSet( 'DependencyTypes', 'FieldSpecs', 'Bundles', 'Providers', 'Actions', 'ETLScripts', 'Recipes', 'Tags', 'AssetData', 'AssetViews', 'Events', 'AppTypes', 'DeviceTypes', 'Teams', 'TaskCategories' )] [String[]]$Exclude, [Parameter(Mandatory = $false, Position = 4)] [String[]]$ProviderName, [Parameter(Mandatory = $false, Position = 5)] [AllowNull()] [String]$OutPath = $null ) begin { # Get the session configuration Write-Verbose "Checking for cached TMSession" $TMSessionConfig = $global:TMSessions[$TMSession] Write-Debug "TMSessionConfig:" Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5) if (-not $TMSessionConfig) { throw "TMSession '$TMSession' not found. Use New-TMSession command before using features." } if (!(Get-Module 'TMD.Common')) { Import-Module 'TMD.Common' } # Default to the reference design directory if an out path wasn't specified if ([String]::IsNullOrWhiteSpace($OutPath)) { $OutPath = Join-Path $Global:userPaths.referencedesigns 'Exported' } # Set up a configuration object to determine which components to install later in the process block $Components = @{ DependencyTypes = $true FieldSpecs = $true Bundles = $true Providers = $true Actions = $true ETLScripts = $true Recipes = $true Tags = $true AssetData = $true AssetViews = $true Events = $true AppTypes = $true DeviceTypes = $true Teams = $true TaskCategories = $true } # Process the Exclude parameter and turn components off $Exclude | ForEach-Object { $Components.$_ = $false } # Determine the project to export if (-not [String]::IsNullOrWhiteSpace($Project) -and ($TMSessionConfig.userContext.project.name -ne $Project)) { Enter-TMProject -ProjectName $Project -TMSession $TMSession } else { $Project = $TMSessionConfig.userContext.project.name } # Set the name to the project name if it wasn't provided $Name = [String]::IsNullOrWhiteSpace($Name) ? $Project : $Name Write-Host 'Starting Export from Server: ' -NoNewline Write-Host $TMSessionConfig.TMServer -ForegroundColor Yellow -NoNewline Write-Host ', Project: ' -NoNewline Write-Host $Project -ForegroundColor Magenta -NoNewline $FilterByProvider = $false if ($ProviderName) { Write-Host ', Export limited to Provider: ' -NoNewline Write-Host $ProviderName -ForegroundColor Cyan $FilterByProvider = $true } else { Write-Host ', Collecting ' -NoNewline Write-Host 'All Providers' -ForegroundColor Cyan } } process { # Set up the directory structure for all of the output files $OutputDirectory = Join-Path $OutPath $TMSessionConfig.TMServer $Name $ReferenceDesignDirectory = Join-Path $OutputDirectory '_REFERENCE DESIGN' $ReferenceDataDirectory = Join-Path $OutputDirectory '_REFERENCE DATA' $ActionDirectory = Join-Path $ReferenceDesignDirectory 'Actions' $ETLDirectory = Join-Path $ReferenceDesignDirectory 'ETL' $RecipeDirectory = Join-Path $ReferenceDesignDirectory 'Recipes' Test-FolderPath $ReferenceDesignDirectory Test-FolderPath $ActionDirectory Test-FolderPath $ETLDirectory Test-FolderPath $RecipeDirectory Test-FolderPath (Join-Path $OutputDirectory 'Documentation') Test-FolderPath (Join-Path $OutputDirectory '_REFERENCE DATA') ## ## Export all of the components ## # Export the Dependency Types if ($Components.DependencyTypes) { Write-Host 'Exporting Dependency Types...' $DependencyTypes = Get-TMDependencyType -ResetIDs -TMSession $TMSession if (!$DependencyTypes) { Write-Host "`tNo Dependency Types to export" } else { $DependencyTypesFilePath = Join-Path $ReferenceDesignDirectory 'DependencyTypes.json' $DependencyTypes | ConvertTo-Json -Depth 100 | Set-Content -Path $DependencyTypesFilePath -Force Write-Host "`t$($DependencyTypes.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Dependency Type(s) exported to '$DependencyTypesFilePath'" } } # Export the App Types if ($Components.AppTypes) { Write-Host 'Exporting App Types...' $AppTypes = Get-TMAssetOption -Type 'App Type' -ResetIDs -TMSession $TMSession if (!$AppTypes) { Write-Host "`tNo App Types to export" } else { $AppTypesFilePath = Join-Path $ReferenceDesignDirectory 'AppTypes.json' $AppTypes | ConvertTo-Json -Depth 100 | Set-Content -Path $AppTypesFilePath -Force Write-Host "`t$($AppTypes.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "App Type(s) exported to '$AppTypesFilePath'" } } # Export the Device Types if ($Components.DeviceTypes) { Write-Host 'Exporting Device Types...' $DeviceTypes = Get-TMAssetOption -Type 'Asset Type' -ResetIDs -TMSession $TMSession if (!$DeviceTypes) { Write-Host "`tNo Device Types to export" } else { $DeviceTypesFilePath = Join-Path $ReferenceDesignDirectory 'DeviceTypes.json' $DeviceTypes | ConvertTo-Json -Depth 100 | Set-Content -Path $DeviceTypesFilePath -Force Write-Host "`t$($DeviceTypes.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Device Type(s) exported to '$DeviceTypesFilePath'" } } # Export the Task Categories if ($Components.TaskCategories) { Write-Host 'Exporting Task Categories...' $TaskCategories = Get-TMAssetOption -Type 'Task Category' -ResetIDs -TMSession $TMSession if (!$TaskCategories) { Write-Host "`tNo Task Categories to export" } else { $TaskCategoriesFilePath = Join-Path $ReferenceDesignDirectory 'TaskCategories.json' $TaskCategories | ConvertTo-Json -Depth 100 | Set-Content -Path $TaskCategoriesFilePath -Force Write-Host "`t$($TaskCategories.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Task Categories exported to '$TaskCategoriesFilePath'" } } # Export the Field Specs if ($Components.FieldSpecs) { Write-Host 'Exporting Field Specs...' $FieldSpecs = Get-TMFieldSpecs -ResetIDs -CustomOnly -TMSession $TMSession if (!$FieldSpecs) { Write-Host "`tNo Asset Field Specs to export" } else { $FieldSpecsFilePath = Join-Path $ReferenceDesignDirectory 'FieldSpecs.json' $FieldSpecs | ConvertTo-Json -Depth 100 | Set-Content -Path $FieldSpecsFilePath -Force Write-Host "`t$($FieldSpecs.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Asset Field Spec(s) exported to '$FieldSpecsFilePath'" } } # Export the Bundles if ($Components.Bundles) { Write-Host 'Exporting Bundles...' $Bundles = Get-TMBundle -ResetIDs -TMSession $TMSession if (!$Bundles) { Write-Host "`tNo Bundles to export" } else { $BundlesFilePath = Join-Path $ReferenceDesignDirectory 'Bundles.json' $Bundles | ConvertTo-Json -Depth 100 | Set-Content -Path $BundlesFilePath -Force Write-Host "`t$($Bundles.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Bundle(s) exported to '$BundlesFilePath'" } } # Export the Events if ($Components.Events) { Write-Host 'Exporting Events...' $Events = Get-TMEvent -ResetIDs -TMSession $TMSession if (!$Events) { Write-Host "`tNo Events to export" } else { $EventsFilePath = Join-Path $ReferenceDesignDirectory 'Events.json' $Events | ConvertTo-Json -Depth 100 | Set-Content -Path $EventsFilePath -Force Write-Host "`t$($Events.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Event(s) exported to '$EventsFilePath'" } } # Export the Events if ($Components.Teams) { Write-Host 'Exporting Teams...' $Teams = Get-TMTeam -TMSession $TMSession if (!$Teams) { Write-Host "`tNo Teams to export" } else { $TeamsFilePath = Join-Path $ReferenceDesignDirectory 'Teams.json' $Teams | ConvertTo-Json -Depth 100 | Set-Content -Path $TeamsFilePath -Force Write-Host "`t$($Teams.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Team(s) exported to '$TeamsFilePath'" } } # Export the Providers if ($Components.Providers) { Write-Host 'Exporting Providers...' $Providers = Get-TMProvider -ResetIDs -TMSession $TMSession if (!$Providers) { Write-Host "`tNo Providers to export" } else { if ($FilterByProvider) { $Providers = $Providers | Where-Object Name -In $ProviderName } $ProvidersFilePath = Join-Path $ReferenceDesignDirectory 'Providers.json' $Providers | ConvertTo-Json -Depth 100 | Set-Content -Path $ProvidersFilePath -Force Write-Host "`t$($Providers.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Provider(s) exported to '$ProvidersFilePath'" } } # Export the Actions if ($Components.Actions) { Write-Host 'Exporting Actions...' $ActionsFolderPath = Join-Path $ReferenceDesignDirectory 'Actions' $Actions = Get-TMAction -SaveCodePath $ActionsFolderPath -ProviderName $ProviderName -ResetIDs -Passthru -TMSession $TMSession if (!$Actions) { Write-Host "`tNo Actions to export" } else { Write-Host "`t$($Actions.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Action(s) exported to '$ActionsFolderPath'" } } # Export the ETL Scripts if ($Components.ETLScripts) { Write-Host 'Exporting ETL Scripts...' $ETLScriptsFolderPath = Join-Path $ReferenceDesignDirectory 'ETL' $ETLScripts = Get-TMETLScript -ResetIDs -SaveCodePath $ETLScriptsFolderPath -ProviderName $ProviderName -Passthru -TMSession $TMSession if (!$ETLScripts) { Write-Host "`tNo ETL Scripts to export" } else { # TODO: Is the 'Private' folder supposed to be excluded? Write-Host "`t$($ETLScripts.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "ETL Script(s) exported to '$ETLScriptsFolderPath'" } } # Export the Recipes if ($Components.Recipes) { Write-Host 'Exporting Recipes...' $RecipesFolderPath = Join-Path $ReferenceDesignDirectory 'Recipes' $Recipes = Get-TMRecipe -ResetIDs -SaveCodePath $RecipesFolderPath -Passthru -TMSession $TMSession if (!$Recipes) { Write-Host "`tNo Recipes to export" } else { # TODO: Is the 'Private' folder supposed to be excluded? Write-Host "`t$($Recipes.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Recipe(s) exported to '" -NoNewline Write-Host "$RecipesFolderPath" -NoNewline Write-Host "'" } } # Export the Tags if ($Components.Tags) { Write-Host 'Exporting Tags...' $Tags = Get-TMTag -ResetIDs -TMSession $TMSession if (!$Tags) { Write-Host "`tNo Tags to export" } else { $TasksFilePath = Join-Path $ReferenceDesignDirectory 'Tags.json' $Tags | ConvertTo-Json -Depth 100 | Set-Content -Path $TasksFilePath -Force Write-Host "`t$($Tags.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "Tags(s) exported to '$TasksFilePath'" } } # Export the AssetViews if ($Components.AssetViews) { Write-Host 'Exporting AssetViews...' $AssetViews = Get-TMAssetViewConfiguration -ResetIDs -TMSession $TMSession if (!$AssetViews) { Write-Host "`tNo AssetViews to export" } else { $TasksFilePath = Join-Path $ReferenceDesignDirectory 'AssetViews.json' $AssetViews | ConvertTo-Json -Depth 100 | Set-Content -Path $TasksFilePath -Force Write-Host "`t$($AssetViews.Count) " -NoNewline -ForegroundColor DarkBlue Write-Host "AssetView(s) exported to '$TasksFilePath'" } } # Export Asset Data if ($Components.AssetData) { Write-Host 'Exporting Asset Data...' Export-TMExcel -Path $ReferenceDataDirectory -TMSession $TMSession Write-Host "`tAsset Data exported to '$ReferenceDataDirectory'" } Write-Host 'Creating package.json file...' New-TMReferenceDesignPackageFile -Name $Name -Path $OutputDirectory } } function New-TMReferenceDesignPackageFile { <# .SYNOPSIS Creates a new package.json file for a locally downloaded/exported Reference Design .DESCRIPTION This function will look at the .PARAMETER Name Parameter description .PARAMETER Path Parameter description .PARAMETER Description Parameter description .PARAMETER Author Parameter description .PARAMETER Email Parameter description .PARAMETER Passthru A switch indicating that the created package object should be sent back to the caller .EXAMPLE New-TMReferenceDesignPackageFile -Name 'TM - Rules Engine' -Path 'C:\DEV\Downloaded Reference Design' .EXAMPLE $PackageSplat = @{ Name = VMware - vCenter' Path = 'C:\Users\user\TMD_Files\Reference Designs\Downloaded\VMware - vCenter' Description = 'This is a detailed description of the Reference Design' Author = 'Me' Email = 'me@tdsi.com' } New-TMReferenceDesignPackageFile @PackageSplat .EXAMPLE $RDPackage = New-TMReferenceDesignPackageFile -Name 'New RD' -Path 'C:\DEV\RD' -Passthru Write-Host "There are $($RDPackage.Inventory.actions.Count) action(s) included in this Reference Design" .OUTPUTS A [PSCustomObject] if -Passthru is specified, otherwise nothing #> param( [Parameter(Mandatory = $true, Position = 0)] [String]$Name, [Parameter(Mandatory = $true, Position = 1)] [ValidateScript( { (Get-Item $_) -is [System.IO.DirectoryInfo] })] [String]$Path, [Parameter(Mandatory = $false, Position = 2)] [String]$Description, [Parameter(Mandatory = $false, Position = 3)] [String]$Author, [Parameter(Mandatory = $false, Position = 4)] [String]$Email, [Parameter(Mandatory = $false)] [Switch]$Passthru ) $Inventory = @{ actions = [System.Collections.ArrayList]::new() etlScripts = [System.Collections.ArrayList]::new() recipes = [System.Collections.ArrayList]::new() bundles = [System.Collections.ArrayList]::new() providers = [System.Collections.ArrayList]::new() dependencyTypes = [System.Collections.ArrayList]::new() fieldSpecs = @{} } $RDPath = Join-Path $Path '_REFERENCE DESIGN' ## Read the Actions Folder to get the name of Scripts $ActionFiles = Get-ChildItem -Path (Join-Path $RDPath 'Actions') -Recurse | Where-Object { $_.Name -like '*.ps1' } foreach ($ActionFile in $ActionFiles) { ## Convert the Script into a proper ActionObject $Action = Read-TMActionScriptFile -Path $ActionFile.FullName ## Some files are not setup or created with all of the metadata. Fill in details based on the filename. if (-Not $Action.Name) { ## Add this Action to the Actions array for writing to JSON [void]$Inventory.Actions.Add( [PSCustomObject]@{ name = $ActionFile.BaseName description = '' } ) } else { ## Add this Action to the Actions array for writing to JSON [void]$Inventory.Actions.Add( [PSCustomObject]@{ name = $Action.Name description = $Action.Description } ) } } ## Read the ETL Scripts Folder to get the name Scripts $ETLFiles = Get-ChildItem -Path (Join-Path $RDPath 'ETL') -Recurse | Where-Object { $_.Name -like '*.groovy' } foreach ($ETLFile in $ETLFiles) { ## Convert the Script into a proper TMETLScript Object $EtlScript = Read-TMETLScriptFile -Path $ETLFile.FullName -ErrorAction 'SilentlyContinue' ## Some files are not setup or created with all of the metadata. Fill in details based on the filename. if (-Not $EtlScript) { [void]$Inventory.ETLScripts.Add( [PSCustomObject]@{ name = $ETLFile.name description = '' } ) } else { ## Add this ETL Script to the array for writing to JSON [void]$Inventory.ETLScripts.Add( [PSCustomObject]@{ name = $EtlScript.name description = $EtlScript.description } ) } } ## Read the Recipes Folder to get the name Scripts $RecipeFiles = Get-ChildItem -Path (Join-Path $RDPath 'Recipes') -Recurse | Where-Object { $_.Name -like '*.groovy' } foreach ($RecipeFile in $RecipeFiles) { ## Convert the Script into a proper TMRecipeScript Object $Recipe = Read-TMRecipeScriptFile -Path $RecipeFile.FullName ## Some files are not setup or created with all of the metadata. Fill in details based on the filename. if (-Not $Recipe) { ## Add this Recipe Script to the array for writing to JSON [void]$Inventory.Recipes.Add( [PSCustomObject]@{ name = $RecipeFile.name description = $RecipeFile.description } ) } else { ## Add this Recipe Script to the array for writing to JSON [void]$Inventory.Recipes.Add( [PSCustomObject]@{ name = $Recipe.name description = $Recipe.description } ) } } # Get the bundles to add to the inventory $BundleFile = Join-Path $RDPath 'Bundles.json' if (Test-Path -Path $BundleFile) { Get-Content -Path $BundleFile | ConvertFrom-Json | ForEach-Object { [void]$Inventory.Bundles.Add( [PSCustomObject]@{ name = $_.name description = $_.description } ) } } # Get the providers to add to the inventory $ProvidersFile = Join-Path $RDPath 'Providers.json' if (Test-Path $ProvidersFile) { Get-Content -Path $ProvidersFile | ConvertFrom-Json | ForEach-Object { [void]$Inventory.Providers.Add( [PSCustomObject]@{ name = $_.name description = $_.description } ) } } # Get the Dependency Types to add to the inventory $DependencyTypesFile = Join-Path $RDPath 'DependencyTypes.json' if (Test-Path $DependencyTypesFile) { Get-Content -Path $DependencyTypesFile | ConvertFrom-Json | ForEach-Object { [void]$Inventory.DependencyTypes.Add($_.label) } } # Get the field specs to add to the inventory $FieldSpecsFile = Join-Path $RDPath 'FieldSpecs.json' if (Test-Path $FieldSpecsFile) { $AllFieldSpecs = Get-Content -Path $FieldSpecsFile | ConvertFrom-Json 'application', 'database', 'device', 'storage' | ForEach-Object { $Domain = $_ $Inventory.FieldSpecs.Add($Domain, @()) $AllFieldSpecs.$_.fields | ForEach-Object { $Inventory.FieldSpecs.$Domain += [PSCustomObject]@{ name = $_.label type = $_.control } } } } # Create the package object which will be written to a file $Package = [PSCustomObject]@{ name = $Name.ToLower().Replace(' - ', '-').Replace(' ', '-') version = '1.0.0' productName = $Name description = $Description ?? '' homepage = '' email = $Email ?? '' author = $Author ?? '' published = $false referenceDesign = @{ compatibility = @{ transitionManager = @{ minVer = '' maxVer = '' } tmd = @{ minVer = '' maxVer = '' } powershell = @{ minVer = '' maxVer = '' } referenceDesigns = @() designSpecific = @() } dependencies = @{ installedApplications = @( @{ name = 'PowerShell' type = 'Software' version = "^$($PSVersionTable.PSVersion.ToString())" source = 'https://www.github.com/TransitionManager/TMD-Resources/PowerShell' } ) powershellModules = @( @{ name = '<PLACEHOLDER>' version = '1.0.0' source = '' } ) referenceDesigns = @( @{ name = '<PLACEHOLDER>' version = '1.0.0' } ) } } inventory = $Inventory } # Create the file $Package | ConvertTo-Json -Depth 5 | Set-Content -Path (Join-Path $Path 'package.json') -Force # Send the package back if Passthru was specified if ($Passthru) { $Package } } |