Functions/Private/Artifacts/IIS/Generate_IIS.ps1
Function Generate_IIS { <# .SYNOPSIS Generates Dockerfile contents for Internet Information Services (IIS) feature .PARAMETER ManifestPath The filesystem path where the JSON manifests are stored. .PARAMETER ArtifactParam Optional - one or more Website names to include in the output. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess",'')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments",'')] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $MountPath, [Parameter(Mandatory = $true)] [string] $ManifestPath, [Parameter(Mandatory = $false)] [string[]] $ArtifactParam ) function IncludePath([string[]] $pathParts) { if ($ArtifactParam -eq $null){ return $true } ForEach ($param in $ArtifactParam){ $parts = $param.Split('/', [System.StringSplitOptions]::RemoveEmptyEntries) $comp = Compare-Object $parts $pathParts if ($comp -eq $null -Or $comp -isnot [System.Array]) { return $true } $indicators = $comp | Foreach-Object { $_.SideIndicator } | Select-Object -unique return ($indicators).Count -eq 1 } return $false } function ProcessDirectory([System.Text.StringBuilder] $DirectoryBuilder, [System.Text.StringBuilder] $CopyBuilder, [System.Text.StringBuilder] $AclBuilder, [string] $SourcePath, [bool] $FirstDirectory) { Write-Verbose "Processing source directory: $SourcePath" $targetPath = $SourcePath.Substring(2) # skip the local drive letter if ($FirstDirectory -eq $true) { $newPath = "RUN New-Item -Path 'C:$targetPath' -Type Directory -Force; ``" } else { $newPath = " New-Item -Path 'C:$targetPath' -Type Directory -Force; ``" } $null = $DirectoryBuilder.AppendLine($newPath) $copy = 'COPY ["{0}", "{1}"]' -f (Split-Path $SourcePath -Leaf),($targetPath -Replace "\\","/") $null = $CopyBuilder.AppendLine($copy) $null = $AclBuilder.AppendLine('RUN $path=' + "'C:$targetPath'; ``") $null = $AclBuilder.AppendLine(' $acl = Get-Acl $path; `') $null = $AclBuilder.AppendLine(' $newOwner = [System.Security.Principal.NTAccount](''BUILTIN\IIS_IUSRS''); `') $null = $AclBuilder.AppendLine(' $acl.SetOwner($newOwner); `') $null = $AclBuilder.AppendLine(' dir -r $path | Set-Acl -aclobject $acl') $fullSourcePath = $SourcePath if ($global:SourceType -eq [SourceType]::Image -or $global:SourceType -eq [SourceType]::Remote) { $fullSourcePath = $MountPath + $targetPath } Copy-Item $fullSourcePath $ManifestPath -Recurse -Force } $ArtifactName = Split-Path -Path $PSScriptRoot -Leaf Write-Verbose -Message ('Generating result for {0} component' -f (Split-Path -Path $PSScriptRoot -Leaf)) $Manifest = '{0}\{1}.json' -f $ManifestPath, $ArtifactName $ResultBuilder = GetDockerfileBuilder $Artifact = Get-Content -Path $Manifest -Raw | ConvertFrom-Json if ($Artifact.Status -eq 'Present') { Write-Verbose ('Copying {0} configuration files' -f $ArtifactName) $ConfigPath = $MountPath + "\" + "Windows\System32\inetsrv\config" if (Test-Path -Path $ConfigPath) { Copy-Item $ConfigPath $ManifestPath -Recurse } $DockerfileTemplate = 'Dockerfile-IIS.template' if ($Artifact.AspNetStatus -eq 'Present') { $DockerfileTemplate = 'Dockerfile-ASPNET.template' } if ($Artifact.AspNet35Status -eq 'Present') { $DockerfileTemplate = 'Dockerfile-ASPNET-35.template' } $ResultBuilder = GetDockerfileBuilder($DockerfileTemplate) if ($Artifact.FeatureName.length -gt 0) { $null = $ResultBuilder.AppendLine("RUN Enable-WindowsOptionalFeature -Online -FeatureName $($Artifact.FeatureName.Replace(';',','))") $null = $ResultBuilder.AppendLine('') } if ($Artifact.HttpHandlers.Count > 0) { Write-Verbose -Message ('Writing instruction to add HTTP handlers') $null = $ResultBuilder.Append('RUN ') foreach ($HttpHandler in $Artifact.HttpHandlers) { $null = $ResultBuilder.AppendLine('New-WebHandler -Name "{0}" -Path "{1}" -Verb "{2}" `' -f $HttpHandler.Name, $HttpHandler.Path, $HttpHandler.Verb) } $null = $ResultBuilder.AppendLine('') } for ($i=0;$i -lt $Artifact.Websites.Count;$i++) { $Site = $Artifact.Websites[$i] $include = IncludePath($Site.Name) if ($include -ne $true){ Write-Verbose "** Skipping site path: $($Site.Name)" continue } if ($Site.Applications -is [system.array]){ $mainApp = $Site.Applications.where{$_.Path -eq '/' } } else { $mainApp = $Site.Applications } if ($mainApp.VirtualDirectories -is [system.array]){ $mainVirtualDir = $mainApp.VirtualDirectories.where{$_.Path -eq '/' } } else { $mainVirtualDir = $mainApp.VirtualDirectories } $mainBinding = $Site.Bindings[0] Write-Verbose -Message ('Writing instruction to create site {0}' -f $Site.Name) # process the main site path $DirectoryBuilder = New-Object System.Text.StringBuilder $CopyBuilder = New-Object System.Text.StringBuilder $AclBuilder = New-Object System.Text.StringBuilder ProcessDirectory -DirectoryBuilder $DirectoryBuilder -CopyBuilder $CopyBuilder -AclBuilder $AclBuilder -SourcePath $mainVirtualDir.PhysicalPath -FirstDirectory $true # creating the website creates the default app & vdir underneath it $sourcePath = $mainVirtualDir.PhysicalPath $targetPath = $sourcePath.Substring(2) $newSite = "RUN New-Website -Name '$($Site.Name)' -PhysicalPath 'C:$targetPath' -Port $($mainBinding.BindingInformation.split(':')[-2]) -Force; ``" $AppBuilder = New-Object System.Text.StringBuilder $null = $AppBuilder.AppendLine($newSite) # now create additional apps and vdirs ForEach ($application in $Site.Applications) { $appVirtualDir = $application.VirtualDirectories.where{$_.Path -eq '/' } $appName = $application.Path.Substring(1) #remove initial '/' $include = IncludePath($Site.Name, $appName) if ($appName.Length -gt 0 -And $include -ne $true){ Write-Verbose "** Skipping app path: $($Site.Name)$($application.Path)" continue } if ($appName.Length -gt 0) { Write-Verbose -Message ('Creating web app {0}' -f $appName) $sourcePath = $appVirtualDir.PhysicalPath $targetPath = $sourcePath.Substring(2) $newApp = " New-WebApplication -Name '$appName' -Site '$($Site.Name)' -PhysicalPath 'C:$targetPath' -Force; ``" $null = $AppBuilder.AppendLine($newApp) if ($sourcePath -ne $mainVirtualDir.PhysicalPath) { ProcessDirectory -DirectoryBuilder $DirectoryBuilder -CopyBuilder $CopyBuilder -SourcePath $sourcePath } } $virtualDirectories = $application.VirtualDirectories.where{$_.Path -ne '/' } ForEach ($virtualDir in $virtualDirectories) { $dirName = $virtualDir.Path.Substring(1) #remove initial '/' $include = IncludePath($Site.Name, $appName, $dirName) if ($dirName.Length -gt 0 -And $include -ne $true){ Write-Verbose "** Skipping vdir path: $($Site.Name)$($application.Path)$($virtualDir.Path)" continue } Write-Verbose -Message ('Creating virtual directory {0}' -f $dirName) $sourcePath = $virtualDir.PhysicalPath $targetPath = $sourcePath.Substring(2) $newDir = '' if ($appName.Length -gt 0) { $newDir = " New-WebVirtualDirectory -Name '$dirName' -Application '$appName' -Site '$($Site.Name)' -PhysicalPath 'C:$targetPath'; ``" } else { $newDir = " New-WebVirtualDirectory -Name '$dirName' -Site '$($Site.Name)' -PhysicalPath 'C:$targetPath'; ``" } $null = $AppBuilder.AppendLine($newDir) if ($sourcePath -ne $mainVirtualDir.PhysicalPath) { ProcessDirectory -DirectoryBuilder $DirectoryBuilder -CopyBuilder $CopyBuilder -SourcePath $sourcePath } } } $null = $ResultBuilder.AppendLine("# Set up website: $($Site.Name)") $null = $ResultBuilder.AppendLine($DirectoryBuilder.ToString().Trim().TrimEnd('``')) $null = $ResultBuilder.AppendLine('') $null = $ResultBuilder.AppendLine($AppBuilder.ToString().Trim().TrimEnd('``')) $null = $ResultBuilder.AppendLine('') Write-Verbose -Message ('Writing instruction to expose port for site {0}' -f $Site.Name) $null = $ResultBuilder.AppendLine("EXPOSE $($mainBinding.BindingInformation.split(':')[-2])") $null = $ResultBuilder.AppendLine('') $null = $ResultBuilder.AppendLine($CopyBuilder.ToString().Trim().TrimEnd('``')) $null = $ResultBuilder.AppendLine('') $null = $ResultBuilder.AppendLine($AclBuilder.ToString().Trim().TrimEnd('``')) $null = $ResultBuilder.AppendLine('') } } return $ResultBuilder.ToString() } |