Summary: The future shapes up for Oliver, and he plays with a new string feature in Windows PowerShell.
Note This is the final post in a series. To catch up, read:
- Oliver Script: A Holiday Tale–Part 1
- Oliver Script: A Holiday Tale–Part 2
- Oliver Script: A Holiday Tale–Part 3
- Oliver Script: A Holiday Tale–Part 4
- Oliver Script: A Holiday Tale–Part 5
- Oliver Script: A Holiday Tale–Part 6
When we left Oliver, he was experiencing some health issues, but after several weeks of rest, he was ready to get back to work. It turned out that his illness would always be with him, but it was controllable. No more triple sugar-triple caffeine coffees for him!
He was happy to be back working with technology again. He was working on a few new projects when a co-worker came up to him with a problem.
Charley had been tasked with spinning up labs for the internal team in addition to labs for client sites. “Oliver, I know that internally we can use System Center 2012 R2 Virtual Machine Manager. But some of the clients are not licensed for it or they are too small to budget for it.”
“To make this even trickier, another challenge is that our boss wants this solution to work as an on-premise solution and as something that could be leveraged in Azure. So I need an easy, but robust, method for deploying at least the configurations on servers.”
“As you can see,” Charley gestured to a shiny spot on his desk where he had been banging his head, “I’ve been having a hard time with this.”
Oliver grimaced and handed Charley some aspirin and ice. “Would you believe me if I told you the answer is simple with Windows PowerShell?”
Charley put up his hands, “Oh! I was halfway there! I was writing this really amazing script, but it was getting out of control. That’s why I figured I’d tap you on the shoulder.”
The young lad smiled and shook his head, “We won’t even need a script to set up the bulk of the environment, only a feature in Windows PowerShell 4.0 called Desired State Configuration (DSC). Let’s say we need to spin up a new website with some files. How would you do that normally?”
Charley thought for a moment, “I could write a Windows PowerShell script to install the needed features with Install-WindowsFeature, then maybe copy the data over with Copy-Item.” He showed Oliver a simple script in Windows PowerShell to do this:
Install-WindowsFeature Web-Server
Install-WindowsFeature Web-Asp-Net45
Install-WindowsFeature Web-Basic-Auth
Copy-Item \\Webfiles\Source\Website c:\inetpub\wwwroot -recurse
“But the problem with this script is that there is no error checking—no way to validate that things are going right or wrong. I could add that code, but then it gets more complex. In addition, my bigger challenge is that the people who need to add features to these servers might not be Windows PowerShell gurus.”
Oliver looked up, “All of these problems are actually pretty much eliminated when using Desired State Configuration to deploy these servers. It’s a feature that allows a server to start and then pull and maintain its configuration from a centralized server, or have it pushed from a single source. A very basic configuration using DSC would look like this structure.”
Configuration Name
{
Node ("Computername1","ComputerName2","Computername3")
{
WindowsFeature FriendlyName
{
Ensure = "Present"
Name = "Feature Name"
}
}
}
“Now,” continued Oliver, “we give the configuration a descriptive name and name a computer to target.”
Configuration WebServer
{
Node Contoso-Web1
{
WindowsFeature FriendlyName
{
Ensure = "Present"
Name = "Feature Name"
}
}
}
“Then we populate the features the server needs. In the case of your web server, I see you wanted to be running standard IIS with basic authentication and ASP.NET 4.5. We would add these to the DSC file in the following manner:”
Configuration WebServer
{
Node Contoso-Web1
{
WindowsFeature Website
{
Ensure = "Present"
Name = "Web-Server"
}
WindowsFeature BasicAuth
{
Ensure = "Present"
Name = "Web-Basic-Auth"
}
WindowsFeature AspNet45
{
Ensure = "Present"
Name = "Web-Asp-Net45"
}
}
}
“Your file copy would be an additional block that is added. It looks like this:”
File WebServerContent
{
Ensure = "Present"
SourcePath = "\\Webfiles\Source\Website"
DestinationPath = "C:\Inetpub\wwwroot\"
Type = "Directory"
}
Charley looked at the DSC file. “But so far, all I see is a slightly different representation of my script. What about error checking? I’d like to make sure that the files don’t copy unless IIS is installed properly.”
“That, my friend, is where it all starts to get easy. Instead of putting code in Windows PowerShell that looks like this...”
$Test=Get-WindowsFeature "Web-ASP-Net45"
If ($Test) { Copy-Item \\Webfiles\Source\Website c:\inetpub\wwwroot -recurse }
“…or any other number of validation techniques—in DSC, you can simply add DependsOn to your configuration block. To ensure a massive file copy only occurs if all of the website features are installed, you add one line:”
File WebServerContent
{
Ensure = "Present"
SourcePath = "\\Webfiles\Source\Website"
DestinationPath = "C:\Inetpub\wwwroot\"
Type = "Directory"
DependsOn = "[WindowsFeature]Website","[WindowsFeature]BasicAuth","[WindowsFeature]AspNet45"
}
“Oh!” Charley smiled, “You mean this does all the funky code part?”
“Yup, because that’s a feature in the DSC engine that enables dependencies. This makes sure something only happens if something else worked! Now to apply this configuration—it’s like how a function works. You run it to put in memory and then execute its name.”
Oliver added one line to the bottom of the DSC configuration file, which was its name as defined at the very top:
WebServer
He then saved it as DSCWebServer.ps1 and ran the script in Windows PowerShell. They looked at the console and saw the following output:
“This created a folder that holds the configuration file named WebServer. Contained within this folder is a single .mof file that holds a configuration for the server called Contoso-Web1," Oliver explained.
“To apply this configuration, we use a cmdlet to push the configuration to the remote server by its name. DSC says, ‘Make it so!’—like Picard used to say to Riker.”
Charley laughed at the Star Trek reference. “Next you’ll be telling me Windows PowerShell can breed Tribbles in my servers!” he uttered as he broke into hysterics.
Oliver ran the following command while he helped his giggling friend back to his chair:
START-DSCConfiguration –path C:\DSC\WebServer –verbose
In moments, the remote web server had all the content running.
Charley was floored. “That was cool! So I need to define one of these for each web server? Can I simply copy and paste?”
Grinning, Oliver pointed out, “No, only for each configuration. If you have twenty web servers, you’d add them to the node list or use a parameter, such as $NodeName. Remember it works like a Windows PowerShell function.” Oliver added more nodes in the DSC file:
node ('Contoso-Web1','Contoso-Web2','Contoso-Web3','Contoso-Web4','Contoso-Web5')
He re-ran the WebServer configuration script to demonstrate. Here is the output they saw:
“The best part is...that same DSCConfiguration cmdlet, ran exactly the same way, will now target all of these servers because they are a part of this configuration.”
“But how would this work in Azure? Do I have to make a DSC server or have something special to launch it with?”
“Nope! You simply make two changes to your DSC file: replace Contoso-Web1 with LocalHost and remove the line that calls the configuration file name. Then we upload it to Azure with Windows PowerShell like this:”
Publish-AzureVMDscConfiguration -ConfigurationPath C:\DSC\DSCWebServer.ps1
“Then you add an extra line to your virtual machine installation script in Azure to use that DSC file:”
$vm = Set-AzureVMDSCExtension -VM $vm -ConfigurationArchive "DSCWebServer.ps1.zip" -ConfigurationName "WebServer"
“Whooooaaaaa…” mumbled Charley as his jaw dropped. “Dude! I have to get hopping on this! I could be done by the end of the week! Thanks!"
Oliver ran off to get a cloth to clean up the puddle of drool Charley contributed to the desk. He smiled to himself. He loved trying to help with what he knew about Windows PowerShell. He was glad to have made his co-worker’s day too.
Months passed...
Oliver continued happily tasking on whatever came his way. Then an email arrived. He was shocked because it was marked microsoft.com. “Why would I receive an email from Microsoft?” the poor fellow wondered. He was about to delete it, but he checked the mail header first to verify.
Sure enough—it was from Redmond!
Oliver gasped. Did someone at Microsoft want to consider him for a job? He’d heard about the Microsoft MVPs. Had he been nominated? Oliver thought back to all of the people he had helped over the years with Windows PowerShell...
—There was Mrs. Bedwin. He had saved all of her photos long ago with a simple cmdlet.
—There were his co-workers at his first real IT job. He showed them simple Windows PowerShell commands that saved them many hours of work, allowing to get home to their families at a decent hour.
—His partner from his first job had used Oliver's simple Windows PowerShell ideas to make his company far more efficient than others for managing small business clients.
—Because of Windows PowerShell, the development team and his co-workers from his previous job were able to transition to DevOps more easily.
—At his current job, his knowledge of Windows PowerShell enabled the team to perform projects and migrations in a far more consistent manner than their competition. This included recently introducing DSC to his co-worker.
He opened the email and read through it carefully...
It wasn’t the MVP program.
It was a person recruiting for a Microsoft team! “Would you have time to fill out a questionnaire?” he read.
A tear rolled down his face. He thought for a moment. It seemed not so long ago that he was serving french fries and mopping floors for a living. “Was that really me?”
He very nervously returned to the email. With his hands shaking, he began to type, “Yes! This is Oliver Script…”
Two days later, he was full of excitement and anticipation—on a flight to Redmond! Who would have thought that simply sharing knowledge and giving of himself would pay in its own way?
Years later, they still talk of this little fellow named Oliver Script—a person like you and me, who learned to believe in himself and found that his dreams came true. I’ll bet there’s a little bit of Oliver in you.
Happy holidays from the Scripting Guys! Remember to listen to this year's holiday song, Code Glorious Code. I hope it puts a smile on your face!
We invite you to follow The Scripting Guys on Twitter and Facebook. If you have any questions, send an email to The Scripting Guys at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. Until then, remember eat your cmdlets every day with a dash of creativity.
Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy