Publish-AzureService.ps1
function Publish-AzureService { <# .Synopsis Publishes one or more modules as azure services .Description Publishes one or more modules as azure services, according to the DomainSchematic found in the Pipeworks manifest .Example Get-Module Pipeworks | Publish-AzureService .Link Out-AzureService #> [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, # The VMSize of the deployment [ValidateSet('ExtraSmall','Small','Medium', 'Large', 'Extra-Large', 'XS', 'XL', 'S', 'M', 'L')] [string] $VMSize = 'ExtraSmall', # The name of the deployment [string] $DeploymentName = 'MyPipeworksService', # The directory the deployment will be placed in [string] $DeploymentDirectory = "$home\Documents\Deployments", # If set, deletes local deployments after packaging. [Switch] $CleanupAfterDeployment, # The instance count [Uint32] $InstanceCount = 1, # 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, 5.5 seconds [Timespan] $Buffer = $([Timespan]::FromMilliseconds(5500)), # The operating system family [ValidateSet("2K8R2","2012")] [string] $Os = "2012" ) begin { $progId = Get-Random $serviceDirectories = @() $azureServiceDefinition = New-AzureServiceDefinition -ServiceName $DeploymentName | Add-AzureRole -RoleName $DeploymentName -VMSize $vmSize | Add-AzureStartupTask -ScriptBlock { & "$env:windir\System32\inetsrv\appcmd" "set" "config" "-section:applicationPools" "-applicationPoolDefaults.processModel.idleTimeout:00:00:00" & "$env:windir\System32\inetsrv\appcmd" "set" "config" "-section:applicationPools" "-applicationPoolDefaults.recycling.periodicRestart.time:00:00:00" } -Elevated if ($RemotePowerShellCredential) { # This option doesn't work yet, but I am stubborn, and will leave this code here until I can make it work. $script = @" netsh advfirewall firewall add rule name="Windows Remote Management (HTTP-In)" dir=in action=allow service=any enable=yes profile=any localport=5985 protocol=tcp net user $($RemotePowerShellCredential.UserName) "$($RemotePowerShellCredential.GetNetworkCredential().Password)" /add net localgroup administrators $($RemotePowerShellCredential.UserName) /add schtasks /CREATE /TN "Enable Remoting" /SC WEEKLY /RL HIGHEST /RU $($RemotePowerShellCredential.UserName) /RP $($RemotePowerShellCredential.GetNetworkCredential().Password) /TR "powershell -noprofile -command Enable-PsRemoting -Force -SkipNetworkProfileCheck; Enable-WSManCredSSP -Role Server -Force" /F schtasks /RUN /TN "Enable Remoting" exit 0 "@ $azureServiceDefinition = $azureServiceDefinition | Add-AzureStartupTask -BatchScript $script -Elevated } $moduleNAmes = @() $jobs = @() } process { $moduleNAmes += $name } end { $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 } if (-not (Test-Path $moduleRoot)) { continue } $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') } 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 $azureServiceDefinition = $azureServiceDefinition | Add-AzureWebSite -SiteName "$($moduleName).$($schematics -join '.')" -PhysicalDirectory $moduleServiceParameters.OutputDirectory -HostHeader $domains } } 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 } Write-Progress "Creating Deployment Package" "$DeploymentName" -Id $progId -PercentComplete 100 if ($serviceDirectories) { $outDir = Join-Path $DeploymentDirectory $DeploymentName $azureServiceDefinition | Out-AzureService -OutputPath "$outDir" -InstanceCount $InstanceCount -Os:$Os } if ($CleanupAfterDeployment) { foreach ($s in $serviceDirectories) { Remove-Item -Path $s -Recurse -Force } } else { Write-Progress "Creating Deployment Package" "$DeploymentName" -Id $progId -Completed } } } } |