publish-WebSite.ps1
function Publish-Website { <# .Synopsis Publishes one or more modules as websites .Description Publishes one or more modules as websites, according to the DomainSchematic found in the Pipeworks manifest .Example Get-Module Pipeworks | Publish-WebSite .Link ConvertTo-ModuleService #> [OutputType([IO.FileInfo])] param( # The name of the module [ValidateScript({ if ($psVersionTable.psVersion -lt '3.0') { if (-not (Get-Module $_)) { throw "Module $_ must be loaded" } } return $true })] [Parameter(Mandatory=$true,Position=0,ParameterSetName='LoadedModule',ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)] [Alias('Module')] [string[]] $Name, # If set, will publish items in a background job [Switch] $AsJob, # If set, will wait for all jobs to complete [Switch] $Wait, # The throttle for background jobs. By default, 10 [Uint32] $Throttle, # The buffer between jobs. By default, 3 seconds [Timespan] $Buffer = $([Timespan]::FromSeconds(3)), # If set, will change the authorization mechanism used for the web site. [ValidateSet("Anonymous", "Windows")] [string] $Authorization = "Anonymous" ) begin { $progId = Get-Random $serviceDirectories = @() $moduleNAmes = @() $jobs = @() } process { $moduleNAmes += $name } end { $publishData = @{} $modulesByLocation = @{} $c = 0 foreach ($moduleName in $moduleNames) { if ($psVersionTable.PSVersion -ge '3.0') { $myModulePath = $env:PSModulePath -split ";" | Select-Object -First 1 $moduleRoot = Join-Path $myModulePath $moduleName } else { $RealModule = Get-Module $moduleName $moduleList = @($RealModule.RequiredModules | Select-Object -ExpandProperty Name) + $realModule.Name $perc =($c / $moduleNames.Count) * 100 $c++ Write-Progress "Publishing Modules" "$moduleName" -PercentComplete $perc -Id $progId $module = Get-Module $moduleName if ($module.Path -like "*.ps1") { continue } $moduleRoot = $module | Split-Path | Select-Object -First 1 } $manifestPath = "$moduleRoot\$($modulename).pipeworks.psd1" $pipeworksManifestPath = Join-Path $moduleRoot "$($moduleName).Pipeworks.psd1" $pipeworksManifest = if (Test-Path $pipeworksManifestPath) { try { & ([ScriptBlock]::Create( "data -SupportedCommand Add-Member, New-WebPage, New-Region, Write-CSS, Write-Ajax, Out-Html, Write-Link { $( [ScriptBlock]::Create([IO.File]::ReadAllText($pipeworksManifestPath)) )}")) } catch { Write-Error "Could not read pipeworks manifest for $moduleName" } } if (-not $pipeworksManifest) { Write-Error "No Pipeworks manifest found for $moduleName" continue } if (-not $pipeworksManifest.DomainSchematics) { Write-Error "Domain Schematics not found for $moduleName" continue } $moduleServiceParameters = @{ Name = $moduleName } if ($pipeworksManifest.PublishDirectory) { $baseName = $pipeworksManifest.PublishDirectory } else { $baseName = "${env:SystemDrive}\inetpub\wwwroot\$moduleName" } foreach ($domainSchematic in $pipeworksManifest.DomainSchematics.GetEnumerator()) { if ($pipeworksManifest.AllowDownload) { $moduleServiceParameters.AllowDownload = $true } $domains = $domainSchematic.Key -split "\|" | ForEach-Object { $_.Trim() } $schematics = $domainSchematic.Value if ($schematics -ne "Default") { $moduleServiceParameters.OutputDirectory = "$baseName.$($schematics -join '.')" $moduleServiceParameters.UseSchematic = $schematics } else { $moduleServiceParameters.OutputDirectory = "$baseName" $moduleServiceParameters.Remove('UseSchematic') } $publishData[$moduleServiceParameters.OutputDirectory] = @($domains) $modulesByLocation[$moduleServiceParameters.OutputDirectory] = $moduleName if ($AsJob) { if ($psVersionTable.PSVersion -ge '3.0') { $convertScript = " Import-Module Pipeworks Import-Module $ModuleName " } else { $convertScript = " Import-Module Pipeworks Import-Module '$($moduleList -join "','")';" } $convertScript += " `$ModuleServiceParameters = " $convertScript += $moduleServiceParameters | Write-PowerShellHashtable $convertScript += " ConvertTo-ModuleService @moduleServiceParameters -Force" $convertScript = [ScriptBlock]::Create($convertScript) Write-Progress "Launching Jobs" "$modulename" if ($throttle) { $runningJobs = @($jobs | Where-Object { $_.State -eq "Running" }) while ($runningJobs.Count -ge $throttle) { $runningJobs = @($jobs | Where-Object { $_.State -eq "Running" }) $jobs | Wait-Job -Timeout 1 | Out-Null $jobs | Receive-Job $percent = 100 - ($runningJobs.Count * 100 / $jobs.Count) Write-Progress "Waiting for $Activity to Complete" "$($Jobs.COunt - $runningJobs.Count) out of $($Jobs.Count) Completed" -PercentComplete $percent } } $jobs += Start-Job -Name $moduleName -ScriptBlock $convertScript if ($buffer) { Start-Sleep -Milliseconds $buffer.TotalMilliseconds } } else { ConvertTo-ModuleService @moduleServiceParameters -Force } $serviceDirectories += $moduleServiceParameters.OutputDirectory } } if ((-not $asJob) -or ($AsJob -and $Wait)) { $Activity = "Build $DeploymentName" $runningJobs = $jobs | Where-Object { $_.State -eq "Running" } while ($runningJobs) { $runningJobs = @($jobs | Where-Object { $_.State -eq "Running" }) $jobs | Wait-Job -Timeout 1 | Out-Null $jobs | Receive-Job $percent = 100 - ($runningJobs.Count * 100 / $jobs.Count) Write-Progress "Waiting for $Activity to Complete" "$($Jobs.COunt - $runningJobs.Count) out of $($Jobs.Count) Completed" -PercentComplete $percent } Import-Module WebAdministration -Global -Force foreach ($p in $publishData.GetEnumerator()) { $allSites = Get-Website $AlreadyExists = $allSites | Where-Object {$p.key.Trim("\") -ieq ([Environment]::ExpandEnvironmentVariables($_.physicalPath).Trim("\")) } $ds = @($p.Value) $ds = foreach ($d in $ds) { if ($d -like "*.*") { $d, "$d".Replace(".", "_") } else { $d } } $d = $ds | Select-Object -First 1 $chunks = @($p.Key -split '\\' -ne '') if (-not $AlreadyExists) { $newWeb = New-Website -Name $chunks[-1] -PhysicalPath $p.Key -HostHeader $d } foreach ($d in $ds) { $binding = Get-WebBinding -Name $chunks[-1] -HostHeader $d -ErrorAction SilentlyContinue if (-not $binding) { New-WebBinding -Name $chunks[-1] -HostHeader $d } if ($d -notlike "*.*") { # Put it in etc/hosts if not present $hostLines = @(Get-content "$env:Windir\System32\Drivers\etc\hosts") $usefulHostLines= $hostLines -notlike "#*" if (-not ($usefulHostLines -like "*$d*")) { $hostLines += " 127.0.0.1 $d" $hostLines |Set-Content "$env:Windir\System32\Drivers\etc\hosts" } } } if ($Authorization -eq 'Anonymous') { Set-WebConfigurationProperty -filter /system.webServer/security/authentication/anonymousAuthentication -name enabled -value true -PSPath "IIS:\" -Location "$($chunks[-1])" Set-WebConfigurationProperty -filter /system.webServer/security/authentication/windowsAuthentication -name enabled -value false -PSPath "IIS:\" -Location "$($chunks[-1])" } elseif ($Authorization -eq 'Windows') { Set-WebConfigurationProperty -filter /system.webServer/security/authentication/anonymousAuthentication -name enabled -value false -PSPath "IIS:\" -Location "$($chunks[-1])" Set-WebConfigurationProperty -filter /system.webServer/security/authentication/windowsAuthentication -name enabled -value true -PSPath "IIS:\" -Location "$($chunks[-1])" } } } } } |