The time saved from the automated deployment of both DSC resources and DSC configuration scripts, along with configuration status reporting, was of enough value to allow you to finally start working on those things you would do if only you had the time. You're leaving on time nowadays and coworkers are lining up to take advantage of being added to your list of managed servers.
The target node count has increased significantly. Since you started this project, the company has grown and the Apollo application is handling more requests than ever. The application team decides that the available time for new features is being compromised by having to deploy the company website code named Aurora by themselves. After talking with your boss, both your teams decide to hand off deploying Aurora to you. A couple of knowledge transfer sessions happen later and you have a list of software requirements and configuration steps for Aurora.
Adding the software requirements to your DSC configuration is a piece of cake. All the IIS features required to build a web server on Windows 2012 R2 are already built-in; they just need to be enabled. For security and access restriction reasons, the company has decided that any web server software cannot just be installed on any server that has the application database on it, so you add a new Node statement to your DSC configuration script and a new role to your ConfigurationData hash for web servers.
Getting the website to the target nodes is slightly more difficult. The application team doesn't use MSIs to install the Aurora website and, instead, uses ZIP files that they used xcopy with to transfer to the web server as well as a simple bat script to extract them and overwrite the existing files. They know this is a fragile and error-prone approach and are working to get a better installer made for the site, but it's not high on the priority list. Realizing you can't wait for that to happen, you decide to move forward with what you have right now. After attempting to use the File DSC resource to download the ZIP file, you realize it can't handle remote files over HTTP.
Fortunately, there is a xRemoteFile DSC resource that does exactly what you need. You chain xRemoteFile to an xArchive DSC resource to download and extract the file to a temporary location. Now, you can use the File DSC resource to check whether the destination contents match your extracted folder. All that is left is creating a web application pool and site:
Configuration PantheonDeployment { <# Import-DscResource -Module.. #> Node ($AllNodes).NodeName{ <#..#> } Node ($AllNodes.Where({$_.Roles -contains 'appserver'})).NodeName{ <#..#> } Node ($AllNodes.Where({$_.Roles -contains 'WebServer'})).NodeName { WindowsFeature IIS { Ensure = 'Present' Name = 'Web-Server' } WindowsFeature IISConsole { Ensure = 'Present' Name = 'Web-Mgmt-Console' DependsOn = '[WindowsFeature]IIS' } WindowsFeature IISScriptingTools { Ensure = 'Present' Name = 'Web-Scripting-Tools' DependsOn = '[WindowsFeature]IIS' } WindowsFeature AspNet { Ensure = 'Present' Name = 'Web-Asp-Net45' DependsOn = @('[WindowsFeature]IIS') } xWebsite DefaultSite { Ensure = 'Present' Name = 'Default Web Site' State = 'Stopped' PhysicalPath = 'C:inetpubwwwroot' DependsOn = @('[WindowsFeature]IIS','[WindowsFeature]AspNet') } xRemoteFile DownloadAuroraZip { Uri = $Node.Aurora.Sourcepath DestinationPath = (Join-Path 'C:WindowsTemp' (Split-Path -Path $Node.Aurora.Sourcepath -Leaf)) DependsOn = @('[xWebsite]DefaultSite') } xArchive AuroraZip { Path = (Join-Path 'C:WindowsTemp' (Split-Path -Path $Node.Aurora.Sourcepath -Leaf)) Destination = 'C:WindowsTemp' DestinationType = 'Directory' MatchSource = $true DependsOn = @('[xRemoteFile]DownloadAuroraZip') } File AuroraContent { Ensure = 'Present' Type = 'Directory' SourcePath = Join-Path 'C:WindowsTemp' ([IO.Path]::GetFileNameWithoutExtension($Node.Aurora.Sourcepath)) DestinationPath = $Node.Aurora.DestinationPath Recurse = $true DependsOn = '[xArchive]AuroraZip' } xWebAppPool AuroraWebAppPool { Ensure = "Present" State = "Started" Name = $Node.WebAppPoolName } xWebsite AuroraWebSite { Ensure = 'Present' State = 'Started' Name = $Node.Aurora.WebsiteName PhysicalPath = $Node.Aurora.DestinationPath DependsOn = '[File]AuroraContent' } xWebApplication AuroraWebApplication { Name = $Node.Aurora.WebApplicationName Website = $Node.Aurora.WebSiteName WebAppPool = $Node.Aurora.WebAppPoolName PhysicalPath = $Node.Aurora.DestinationPath Ensure = 'Present' DependsOn = @('[xWebSite]AuroraWebSite') } } } $data = Join-Path $PSScriptRoot 'data_example_04.psd1' $output = Join-Path $PSScriptRoot 'PantheonDeployment' PantheonDeployment -ConfigurationData $data -OutputPath $output
With all this new configuration data to track, it's no wonder you need to update your ConfigurationData hash:
@{ AllNodes = @( @{ NodeName = 'app01' ConfigurationId = 'ab2c2cb2-67a3-444c-bc55-cc2ee70e3d0c' Roles = @('appserver') }, @{ NodeName = 'app02' ConfigurationId = '8e8f44e6-aaac-4060-b072-c9ae780ee5f7' Roles = @('appserver') }, @{ NodeName = 'web01' ConfigurationId = 'b808fb65-5b16-4f83-84c6-aa398a6abdd5' Roles = @('webserver') }, @{ NodeName = '*' RefreshMode = 'Pull' ConfigurationMode = 'ApplyAndAutoCorrect' PSDSCCPullServer = 'https://dsc01:8080/PSDSCPullServer.svc' AllowModuleOverwrite = $true RebootNodeIfNeeded = $true Apollo = @{ Name = 'Apollo' ProductId = '{e70c4829-91dc-4f0e-a404-4eba81f6feb9}' SourcePath = 'http://build.pantheon.net/apollo/packages/releases/apollo.1.1.0.msi' Arguments = '' ConfigFilePath = "$env:ProgramFilesApolloconfigapp.config" ConfigFileContents = "importantsetting=`$true" } Aurora = @{ SourcePath = 'http://build.pantheon.net/aurora/releases/aurora.zip' DestinationPath = "$env:SystemDriveinetpubwwwaurora" WebApplicationName = 'Aurora' WebSiteName = 'Aurora' WebAppPoolName = 'AuroraAppPool' } } ) }
You already have a hash for Apollo, so all you have to do is add a new hash for Aurora with the appropriate details.