functions/Initialize-BicepTemplate.ps1
|
function Initialize-BicepTemplate { <# .SYNOPSIS Initializes a directory with files from a predefined template library. .DESCRIPTION Generates files based on a selected template from a library of templates into a directory. #> [Alias('bicep-init')] [CmdletBinding()] param ( [Parameter()] [System.IO.DirectoryInfo] $Target = '.', [Parameter()] [ValidateSet('deployment', 'registry')] [System.String] $Template = 'deployment', [Parameter()] [System.Collections.Hashtable] $InitParameter ) <# Helper script for copying files. This avoids problems with existing subdirectories on Copy-Item in the staging directory. By only creating subdirectories when they do not exist and then copying all files. #> function Copy-Helper { param( [System.IO.DirectoryInfo] $sourceDir, [System.IO.DirectoryInfo] $targetDir ) $sourceDirs = Get-ChildItem -Recurse -Directory -Path $sourceDir foreach ($dir in $sourceDirs) { $relativePath = Resolve-Path -Relative -Path $dir.FullName -RelativeBasePath $sourceDir $templateDir = [System.IO.DirectoryInfo]::new("$targetDir/$relativePath") if (-NOT $templateDir.Exists) { $null = $templateDir.Create() } } $sourceFiles = Get-ChildItem -Recurse -File -Path $sourceDir foreach ($file in $sourceFiles) { $relativePath = Resolve-Path -Relative -Path $file.FullName -RelativeBasePath $sourceDir $templateFile = [System.IO.FileInfo]::new("$targetDir/$relativePath") if ($templateFile.Exists) { throw [System.InvalidOperationException]::new("$relativePath already exists!") } else { $null = $file.CopyTo($templateFile) } } } <# Initialize all relevant variables: - targetDir where to copy files - sourceDir for the template - commonDir for common files - initPs1 for the template initialization script #> $common = Get-Item -Path "$PSScriptRoot/libary/common" $initPs1 = Get-Item -Path "$PSScriptRoot/libary/$Template/init.ps1" $rootDir = Get-Item -Path "$PSScriptRoot/libary/$Template/root" if (-NOT [System.IO.Path]::IsPathFullyQualified($Target)) { $rootedPath = [System.IO.Path]::Join((Get-Location).Path, $Target) $Target = [System.IO.DirectoryInfo]::new($rootedPath) } try { <# All files are copied to the staging directory, where they are modified and then copied to the target directory. #> $tempDir = "{0}/bicep-staging/{1}" -f [System.IO.Path]::GetTempPath(), [System.Guid]::NewGuid() $tempDir = New-Item -ItemType Directory -Path $tempDir Copy-Helper -sourceDir $rootDir -targetDir $tempDir Copy-Helper -sourceDir $common -targetDir $tempDir . $initPs1 @InitParameter -StagingDir $tempDir <# This is the final copy operation from staging to the user directory Uses the copy dialog for Windows and the shell copy for Linux. #> if (-NOT $Target.Exists) { $Target.Create() } if ($IsWindows) { $destination = New-Object -ComObject "Shell.Application" $destination = $destination.NameSpace($Target.FullName) $destination.CopyHere("$tempDir/*") return } try { Copy-Item -Path "$tempDir/*" -Recurse -Destination $Target Get-ChildItem -Path $tempDir -Hidden | Copy-Item -Recurse -Destination $Target -ErrorAction SilentlyContinue } catch { Write-Host -ForegroundColor RED "`n`nTarget: $Target" Write-Host -ForegroundColor RED "`Files already exist in the target directory." $overwrite = Read-UtilsUserOption -Prompt "Overwrite?" if ($overwrite) { Copy-Item -Path "$tempDir/*" -Recurse -Force -Destination $Target Get-ChildItem -Path $tempDir -Hidden | Copy-Item -Recurse -Force -Destination $Target -ErrorAction SilentlyContinue } else { Write-Host -ForegroundColor RED "`n`nAborting the operation." } } } finally { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue # This cleans up staging directory from directories older than 10 minutes. # In case of a crash, when the staging directory was not deleted. Get-ChildItem -Path $tempDir.Parent -Directory | Where-Object -Property CreationTime -LT (Get-Date).AddMinutes(-10) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } } |