Skip to content
This repository was archived by the owner on Mar 11, 2020. It is now read-only.

Commit 7ba32b5

Browse files
committed
IIS support for multiple apps & virtual directories
Signed-off-by: Elton Stoneman <elton@sixeyed.com>
1 parent caf12d8 commit 7ba32b5

File tree

10 files changed

+219
-55
lines changed

10 files changed

+219
-55
lines changed

Functions/Private/Artifacts/IIS/Discover_IIS.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ else {
6565
}
6666

6767
### Write the result to the manifest file
68-
$ManifestResult | ConvertTo-Json -Depth 3 | Set-Content -Path $Manifest
68+
$ManifestResult | ConvertTo-Json -Depth 6 | Set-Content -Path $Manifest
6969

7070
Write-Verbose -Message ('Finished discovering {0} artifact' -f $ArtifactName)
7171
}

Functions/Private/Artifacts/IIS/Generate_IIS.ps1

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@ $ResultBuilder = New-Object System.Text.StringBuilder
2929
$Artifact = Get-Content -Path $Manifest -Raw | ConvertFrom-Json
3030

3131
if ($Artifact.Status -eq 'Present') {
32+
$DockerfileTemplate = 'Dockerfile-IIS.template'
3233
Write-Verbose ('Copying {0} configuration files' -f $ArtifactName)
3334
$ConfigPath = $Mount.Path + "\" + "Windows\System32\inetsrv\config"
3435
if (Test-Path -Path $ConfigPath) {
3536
Copy-Item $ConfigPath $ManifestPath -Recurse
3637
}
37-
38-
Write-Verbose -Message ('Writing instruction to install IIS')
39-
$null = $ResultBuilder.AppendLine('# Install Windows features for IIS')
40-
$null = $ResultBuilder.Append('RUN Add-WindowsFeature Web-server')
4138
if ($Artifact.AspNetStatus -eq 'Present') {
42-
Write-Verbose -Message ('Writing instruction to install ASP.NET')
43-
$null = $ResultBuilder.Append(', NET-Framework-45-ASPNET, Web-Asp-Net45')
39+
$DockerfileTemplate = 'Dockerfile-ASPNET.template'
4440
}
45-
$null = $ResultBuilder.AppendLine('')
41+
if ($Artifact.AspNet35Status -eq 'Present') {
42+
$DockerfileTemplate = 'Dockerfile-ASPNET-35.template'
43+
}
44+
$Dockerfile = Get-Content -Raw -Path "$ModulePath\Resources\$DockerfileTemplate"
45+
$null = $ResultBuilder.AppendLine($Dockerfile.Trim())
4646

4747
if ($Artifact.FeatureName.length -gt 0) {
4848
$null = $ResultBuilder.AppendLine("RUN Enable-WindowsOptionalFeature -Online -FeatureName $($Artifact.FeatureName.Replace(';',','))")
@@ -58,31 +58,93 @@ if ($Artifact.Status -eq 'Present') {
5858
$null = $ResultBuilder.AppendLine('')
5959
}
6060

61-
$null = $ResultBuilder.AppendLine('')
62-
$null = $ResultBuilder.AppendLine("RUN Remove-Website 'Default Web Site'")
63-
6461
$null = $ResultBuilder.AppendLine('')
6562
for ($i=0;$i -lt $Artifact.Websites.Count;$i++) {
63+
$WebSiteBuilder = New-Object System.Text.StringBuilder
6664
$Site = $Artifact.Websites[$i]
67-
$SitePath = $Mount.Path + $Site.PhysicalPath
68-
Write-Verbose -Message ('Copying website files from {0} to {1}' -f $SitePath, $ManifestPath)
69-
Copy-Item $SitePath $ManifestPath -Recurse
65+
$null = $WebSiteBuilder.AppendLine("# Set up website: $($Site.Name)")
7066

71-
Write-Verbose -Message ('Writing instruction to copy files for {0} site' -f $Site.Name)
72-
$null = $ResultBuilder.AppendLine("# Set up website: $($Site.Name)")
73-
$copy = "COPY {0} {1}" -f (Split-Path $Site.PhysicalPath -Leaf),($Site.PhysicalPath -Replace "\\","/")
74-
$null = $ResultBuilder.AppendLine($copy)
67+
if ($Site.Applications -is [system.array]){
68+
$mainApp = $Site.Applications.where{$_.Path -eq '/' }
69+
}
70+
else {
71+
$mainApp = $Site.Applications
72+
}
73+
if ($mainApp.VirtualDirectories -is [system.array]){
74+
$mainVirtualDir = $mainApp.VirtualDirectories.where{$_.Path -eq '/' }
75+
}
76+
else {
77+
$mainVirtualDir = $mainApp.VirtualDirectories
78+
}
79+
$mainBinding = $Site.Bindings[0]
7580

7681
Write-Verbose -Message ('Writing instruction to create site {0}' -f $Site.Name)
77-
$newSite = 'RUN New-Website -Name ''{0}'' -PhysicalPath "C:{1}" -Port {2} -Force' -f ($Site.Name -replace "'","''"), $Site.PhysicalPath, $Site.binding.bindingInformation.split(':')[-2]
78-
$null = $ResultBuilder.AppendLine($newSite)
7982

80-
Write-Verbose -Message ('Writing instruction to expose port for site {0}' -f $Site.Name)
81-
$null = $ResultBuilder.AppendLine("EXPOSE $($Site.binding.bindingInformation.split(':')[-2])")
83+
# create empty paths for all the site directories
84+
$newPath = "RUN New-Item -Path 'C:$($mainVirtualDir.PhysicalPath)' -Type Directory; ``"
85+
$null = $WebSiteBuilder.AppendLine($newPath)
86+
87+
$sourcePaths = $Site.Applications.VirtualDirectories.PhysicalPath
88+
ForEach ($sourcePath in $sourcePaths) {
89+
if ($sourcePath -ne $mainVirtualDir.PhysicalPath) {
90+
$newPath = " New-Item -Path 'C:$sourcePath' -Type Directory -Force; ``"
91+
$null = $WebSiteBuilder.AppendLine($newPath)
92+
}
93+
}
94+
95+
$null = $ResultBuilder.AppendLine($WebSiteBuilder.ToString().Trim().TrimEnd('``'))
96+
$null = $ResultBuilder.AppendLine('')
97+
$WebSiteBuilder = New-Object System.Text.StringBuilder
98+
99+
# creating the website creates the default app & vdir underneath it
100+
$newSite = "RUN New-Website -Name '$($Site.Name)' -PhysicalPath 'C:$($mainVirtualDir.PhysicalPath)' -Port $($mainBinding.BindingInformation.split(':')[-2]) -Force; ``"
101+
$null = $WebSiteBuilder.AppendLine($newSite)
102+
103+
# now create additional apps and vdirs
104+
ForEach ($application in $Site.Applications) {
105+
$appVirtualDir = $application.VirtualDirectories.where{$_.Path -eq '/' }
106+
$appName = $application.Path.Substring(1) #remove initial '/'
107+
108+
if ($appName.Length -gt 0) {
109+
Write-Verbose -Message ('Creating web app {0}' -f $appName)
110+
$newApp = " New-WebApplication -Name '$appName' -Site '$($Site.Name)' -PhysicalPath 'C:$($appVirtualDir.PhysicalPath)' -Force; ``"
111+
$null = $WebSiteBuilder.AppendLine($newApp)
112+
}
113+
114+
$virtualDirectories = $application.VirtualDirectories.where{$_.Path -ne '/' }
115+
ForEach ($virtualDir in $virtualDirectories) {
116+
$dirName = $virtualDir.Path.Substring(1) #remove initial '/'
117+
Write-Verbose -Message ('Creating virtual directory {0}' -f $dirName)
118+
$newDir = ''
119+
if ($appName.Length -gt 0) {
120+
$newDir = " New-WebVirtualDirectory -Name '$dirName' -Application '$appName' -Site '$($Site.Name)' -PhysicalPath 'C:$($virtualDir.PhysicalPath)'; ``"
121+
}
122+
else {
123+
$newDir = " New-WebVirtualDirectory -Name '$dirName' -Site '$($Site.Name)' -PhysicalPath 'C:$($virtualDir.PhysicalPath)'; ``"
124+
}
125+
$null = $WebSiteBuilder.AppendLine($newDir)
126+
}
127+
}
128+
$null = $ResultBuilder.AppendLine($WebSiteBuilder.ToString().Trim().TrimEnd('``'))
129+
$null = $ResultBuilder.AppendLine('')
130+
131+
Write-Verbose -Message ('Writing instruction to expose port for site {0}' -f $Site.Name)
132+
$null = $ResultBuilder.AppendLine("EXPOSE $($mainBinding.BindingInformation.split(':')[-2])")
82133
$null = $ResultBuilder.AppendLine('')
134+
135+
$sourcePaths = $Site.Applications.VirtualDirectories.PhysicalPath
136+
ForEach ($sourcePath in $sourcePaths) {
137+
$SitePath = $Mount.Path + $sourcePath
138+
Write-Verbose -Message ('Copying website files from {0} to {1}' -f $SitePath, $ManifestPath)
139+
Copy-Item $SitePath $ManifestPath -Recurse -Force
140+
141+
Write-Verbose -Message ('Writing instruction to copy files for {0} site' -f $Site.Name)
142+
$copy = "COPY {0} {1}" -f (Split-Path $sourcePath -Leaf),($sourcePath -Replace "\\","/")
143+
$null = $ResultBuilder.AppendLine($copy)
144+
}
145+
146+
$null = $ResultBuilder.AppendLine('')
83147
}
84-
85-
$null = $ResultBuilder.AppendLine('CMD /Wait-Service.ps1 -ServiceName W3SVC -AllowServiceRestart')
86148
}
87149

88150

Functions/Private/Artifacts/IIS/GetManifestFromApplicationHost.ps1

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ $ManifestResult = @{
3232
FeatureName = ''
3333
Status = 'Absent'
3434
AspNetStatus = 'Absent'
35+
AspNet35Status = 'Absent'
3536
}
3637

3738
$ApplicationHostPath = "$MountPath\Windows\System32\inetsrv\config\applicationHost.config"
@@ -48,16 +49,41 @@ if (Test-Path -Path $ApplicationHostPath) {
4849
if ($ArtifactParam) {
4950
$sites = $sites.where{$_.name -in $ArtifactParam }
5051
}
52+
5153
$Websites = New-Object System.Collections.ArrayList
52-
ForEach ($site in $sites) {
53-
$Websites.add([PSCustomObject]@{
54+
ForEach ($site in $sites) {
55+
56+
$applications = New-Object System.Collections.ArrayList
57+
ForEach ($application in $site.application) {
58+
$virtualDirectories = New-Object System.Collections.ArrayList
59+
ForEach ($virtualDirectory in $application.virtualDirectory){
60+
$virtualDirectories.add([PSCustomObject]@{
61+
Path = $virtualDirectory.path;
62+
PhysicalPath = $virtualDirectory.physicalPath.replace('%SystemDrive%\','\').replace('C:\','\').Replace('c:\','\');
63+
}) | Out-Null
64+
}
65+
$applications.add([PSCustomObject]@{
66+
Path = $application.path;
67+
ApplicationPool = $application.ApplicationPool;
68+
VirtualDirectories = $virtualDirectories;
69+
}) | Out-Null
70+
}
71+
72+
$bindings = New-Object System.Collections.ArrayList
73+
ForEach ($binding in $site.bindings.binding) {
74+
$bindings.add([PSCustomObject]@{
75+
Protocol = $binding.Protocol;
76+
BindingInformation = $binding.bindingInformation
77+
}) | Out-Null
78+
}
79+
80+
$Websites.add([PSCustomObject]@{
5481
Name = $site.name;
5582
ID = $site.id;
56-
ApplicationPool = $site.application.ApplicationPool
57-
PhysicalPath = $site.application.virtualDirectory.physicalPath.replace('%SystemDrive%\','\').replace('C:\','\').Replace('c:\','\');
58-
Binding = [PSCustomObject]@{ Protocol = $site.bindings.binding.Protocol;
59-
BindingInformation = $site.bindings.binding.bindingInformation } }) | Out-Null
60-
}
83+
Applications = $applications;
84+
Bindings = $bindings;
85+
}) | Out-Null
86+
}
6187

6288
$AllApplicationPools = $IISConfig | Select-Xml -XPath "//applicationPools" | Select-Object -ExpandProperty Node
6389
$ApplicationPools = $AllApplicationPools.add.name
@@ -115,6 +141,9 @@ if (Test-Path -Path $ApplicationHostPath) {
115141
if ($AspNetInstalled -eq $true){
116142
$ManifestResult.AspNetStatus = 'Present'
117143
}
144+
145+
#TODO
146+
$ManifestResult.AspNet35Status = 'Absent'
118147
}
119148

120149
return $ManifestResult

Functions/Private/Artifacts/IIS/GetManifestFromMetabase.ps1

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ $ManifestResult = @{
3232
FeatureName = ''
3333
Status = 'Absent'
3434
AspNetStatus = 'Absent'
35+
AspNet35Status = 'Absent'
3536
}
3637

3738
$MetabasePath = "$MountPath\Windows\System32\inetsrv\MetaBase.xml"
@@ -79,6 +80,68 @@ if (Test-Path -Path $MetabasePath) {
7980
}
8081
}
8182

83+
84+
$Websites = New-Object System.Collections.ArrayList
85+
$iis = $IISConfig.configuration.MBProperty
86+
ForEach ($site in $iis.IIsWebServer.where{$_.ServerBindings -ne $null}) {
87+
$siteId = $site.Location
88+
$applications = New-Object System.Collections.ArrayList
89+
90+
# in IIS 6 the app for the website is the root virtual directory
91+
$mainApp = $iis.IIsWebVirtualDir.where{$_.Location -eq "$SiteId/root"}
92+
$virtualDirectories = New-Object System.Collections.ArrayList
93+
$mainVirtualDir = [PSCustomObject]@{
94+
Path = '/';
95+
PhysicalPath = $mainApp.Path.replace('%SystemDrive%\','\').replace('C:\','\').Replace('c:\','\');
96+
}
97+
$virtualDirectories.add($mainVirtualDir) | Out-Null
98+
99+
# virtual directories are IIsWebVirtualDir elements with no app name
100+
ForEach ($virtualDirectory in $iis.IIsWebVirtualDir.where{
101+
$_.Location.StartsWith("$SiteId/root/") -and
102+
$_.AppFriendlyName -eq $null}){
103+
$virtualDirectories.add([PSCustomObject]@{
104+
Path = '/' + $virtualDirectory.Location.Substring("$SiteId/root/".Length);
105+
PhysicalPath = $virtualDirectory.Path.replace('%SystemDrive%\','\').replace('C:\','\').Replace('c:\','\');
106+
}) | Out-Null
107+
}
108+
$applications.add([PSCustomObject]@{
109+
Path = '/';
110+
ApplicationPool = ''; # TODO
111+
VirtualDirectories = $virtualDirectories;
112+
}) | Out-Null
113+
114+
# apps are IisWebDirectory elements with an app name
115+
ForEach ($application in $iis.IIsWebDirectory.where{
116+
$_.Location.StartsWith("$SiteId/root/") -and
117+
$_.AppFriendlyName -ne $null}){
118+
$path = $application.Location.Substring("$SiteId/root/".Length)
119+
$virtualDirectories = New-Object System.Collections.ArrayList
120+
$virtualDirectories.add([PSCustomObject]@{
121+
Path = '/';
122+
PhysicalPath = "$($mainVirtualDir.PhysicalPath)\$path"
123+
}) | Out-Null
124+
$applications.add([PSCustomObject]@{
125+
Path = '/' + $path;
126+
ApplicationPool = $application.AppPoolId;
127+
VirtualDirectories = $virtualDirectories;
128+
}) | Out-Null
129+
}
130+
131+
$bindings = New-Object System.Collections.ArrayList
132+
$bindings.add([PSCustomObject]@{
133+
Protocol = 'http'; #TODO - discover protocol from metabase
134+
BindingInformation = $site.ServerBindings
135+
}) | Out-Null
136+
137+
$Websites.add([PSCustomObject]@{
138+
Name = $site.ServerComment;
139+
ID = $siteId;
140+
Applications = $applications;
141+
Bindings = $bindings;
142+
}) | Out-Null
143+
}
144+
82145
$ManifestResult.FeatureName = ''
83146
$ManifestResult.Status = 'Present'
84147
$ManifestResult.Websites = $Websites
@@ -91,6 +154,9 @@ if (Test-Path -Path $MetabasePath) {
91154
if ($AspNetInstalled -eq $true){
92155
$ManifestResult.AspNetStatus = 'Present'
93156
}
157+
158+
#TODO
159+
$ManifestResult.AspNet35Status = 'Absent'
94160
}
95161

96162
return $ManifestResult

Functions/Private/GenerateDockerfile.ps1

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,15 @@
2525
)
2626

2727
Write-Verbose -Message ('Generating Dockerfile based on discovered artifacts in :{0}' -f $Mount.Path)
28-
### Verify that the Dockerfile template is available
29-
$DockerfileTemplate = '{0}\Resources\Dockerfile-template' -f $ModulePath
28+
$Dockerfile = ''
3029

31-
if (!(Test-Path -Path $DockerfileTemplate)) {
32-
throw 'Couldn''t find the Dockerfile template. Please make sure this exists under: {0}' -f $DockerfileTemplate
33-
}
34-
35-
### Get the Dockerfile template
36-
$Dockerfile = Get-Content -Raw -Path $DockerfileTemplate
37-
$Dockerfile = $Dockerfile.Trim() + [System.Environment]::NewLine
38-
$Result = ''
39-
40-
foreach ($item in $Artifact) {
4130
if (! $ArtifactParam) {
42-
$Result = & "Generate_$item" -ManifestPath $ArtifactPath
31+
$Dockerfile = & "Generate_$Artifact" -ManifestPath $ArtifactPath
4332
}
4433
else {
45-
$Result = & "Generate_$item" -ManifestPath $ArtifactPath -ArtifactParam $ArtifactParam
34+
$Dockerfile = & "Generate_$Artifact" -ManifestPath $ArtifactPath -ArtifactParam $ArtifactParam
4635
}
47-
$Dockerfile += '{0}{1}' -f [System.Environment]::NewLine, $Result.Trim()
48-
}
4936

5037
$DockerfilePath = '{0}\Dockerfile' -f $ArtifactPath
51-
Set-Content -Path $DockerfilePath -Value $Dockerfile
52-
}
53-
38+
Set-Content -Path $DockerfilePath -Value $Dockerfile.Trim()
39+
}

Functions/Public/ConvertTo/ConvertTo-Dockerfile.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
[Parameter(Mandatory = $false)]
8282
[string] $MountPath,
8383

84-
[Parameter(Mandatory = $false)]
84+
[Parameter(Mandatory = $true)]
8585
[string[]] $Artifact,
8686

8787
[Parameter(Mandatory = $false)]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# escape=`
2+
FROM microsoft/aspnet:3.5-windowsservercore-10.0.14393.693
3+
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
4+
5+
RUN Remove-Website 'Default Web Site'; `
6+
If (Test-Path 'C:\inetpub\wwwroot'){ Remove-Item -Path 'C:\inetpub\wwwroot' }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# escape=`
2+
FROM microsoft/aspnet:windowsservercore-10.0.14393.693
3+
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
4+
5+
RUN Remove-Website 'Default Web Site'; `
6+
If (Test-Path 'C:\inetpub\wwwroot'){ Remove-Item -Path 'C:\inetpub\wwwroot' }

Resources/Dockerfile-IIS.template

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# escape=`
2+
FROM microsoft/iis:windowsservercore-10.0.14393.693
3+
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
4+
5+
RUN Remove-Website 'Default Web Site'; `
6+
If (Test-Path 'C:\inetpub\wwwroot'){ Remove-Item -Path 'C:\inetpub\wwwroot' }

0 commit comments

Comments
 (0)