Simple Powershell scripting with Azure Powershell cmdlets

In my last post I covered how you can write bash scripts using the azure cli. Right after posting, @dfinke pinged asking rightfully “What about Powershell? Can I do the same things?”.  Yes Doug, absolutely! In this post I’ll show you can do the same and more in Powershell using our Azure Powershell cmdlets.

Scripting in Powershell

To understand scripting in Powershell, there’s a few things you need to know.

  • Powershell cmdlets write (or should write) objects to the pipeline, not just output text. This is really one of the major differences, you are not writing scripts that have to parse text, deal with regexes etc just to do basic things. Instead you just wire up properties. If you compare to my previous post, you’ll see instantly how this manifests itself and makes life easier.
  • Powershell cmdlets are very fine-grained each performing a specific purpose. You can chain together different cmdlets by piping objects from one cmdlet to the next. You can learn more about piping and the pipeline (and should if you don’t know about it) in Powershell here.
  • Pipelining is a whole topic on it’s own, but basically as long as objects coming from the pipeline have properties that match property names on the destination cmdlet, it should just work.
  • You can create local variables and save objects from previous calls which you can reuse. This is really nice for scripting.

To script with our cmdlets, you will basically call one of the cmdlets and either save the result into a variable that you can pass in, or pipe it directly. In my examples below, you’ll see that in most cases, you just pipe directly.

Below is a list of some common simple scripting scenarios for websites, which includes the cmdlets and a small explanation of what each is doing. This should get you started and you can use a similar approach to work with all of our cmdlets.

Disclaimer, I am not at all a Powershell expert, so there probably are better ways to do what I am showing you.

Stop all running sites

  • Retrieves all websites, this returns a collection of Site objects. Each object is a summary object which has a Name property which is the site name.
  • Pipes to Stop-AzureWebsite (matching Site.Name to the Stop-AzureWebsite Name parameter) which stops each site.

Start all stopped sites

  • Retrieves all websites
  • Pipes to Start-AzureWebsite which starts each site.

Delete all sites

  • Retrieves all websites
  • Pipes to Remove-AzureWebsite which removes each site and passes the force param to force removal without prompting.

Set an app setting to every site

This one may seem a bit strange at first, but read the explanation. You can really see Powershell’s object oriented nature shining through here :-)

  • Retrieves all websites
  • Pipes to For-EachObject which loops through all the objects.
  • The –Process param specifies a script to execute for each object. Within the script $_ refers to the current object.
  • The script first calls Get-AzureWebsite to get the full Website object passing the piped in name which is stored in a $site variable. When Get-AzureWebsite is called for a specific Website it retrieves all the details including the settings.
  • Next it updates the settings for $site with a “Bar” entry. This is important because we don’t want to lose existing settings we just want to update/append.
  • Finally it calls Set-AzureWebsite passing the current site name and the new settings object which contains the old settings and the new Bar setting.

Getting cmdlets to run in the background.

All the previous calls are blocking. Powershell does support the Start-Job cmdlet which allows you spawn things off in the background, so you can modify any of the script to run in the background. This took me a bit of playing, but I finally got the last one working (which is the hardest).

Hold on to your saddles folks! If you thought the last one was a little tough, feast your eyes on this!

  • Retrieves all websites
  • Pipes to For-EachObject which loops through all the objects.
  • The script calls Start-Job to launch a background job
  • The –InputObject specifies to pass the site name as a variable to the job script.
  • The –ScriptBlock specifies the script which executes within the background job (Matrix anyone?)
  • The job script first calls Get-AzureWebsite to retrieve the site info and stores it in the $site variable.
  • Next it sets the the settings.
  • Finally it calls Set-AzureWebsite passing the current site name and the new settings object which contains the old settings and the new Bar setting.

This one actually deserves a screenshot or two, so here goes. Below you can see running the script which outputs the list of created jobs.

image

Now you can see that it has created for me a job for each website that was retrieved. The jobs are running in the background. I can use the Get-Job command to monitor the status of any jobs running in my shell.

image

As you can see above all the jobs completed a few seconds later. There is also a Receive-Job command that you can pass a job to in order to get more details and I believe the Verbose output. In this case Set-AzureWebsite doesn’t return anything, however I can check one of my sites and see that it worked. Notice Bar1…

image

Merry posh scripting

As in my previous post, this is just the beginning of what you can do once you start mastering scripting in Powershell. Just go ask my friend and Powershell guru Peter Provost. We are doing a lot of deliberate up-front thinking about scripting scenarios with our Powershell cmdlets as there are existing mechanisms since it is so core to being a first class Powershell cmdlet.

Let us know if there are areas you think we need to improve the scripting support, and please share links to any cool Azure powershell scripts you have authored!

Happy Holidays!

This entry was posted in azure, powershell. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.irisclasson.com/ Iris Classon

    Yay for the PowerShell stuff :D Keep them coming, I need to learn :)

  • http://blogs.msdn.com/gblock Glenn Block

    The Start-Job example explicitly uses a loop so that each call runs as it’s own job otherwise I found that it just ran the whole thing as a single job.

  • http://blogs.msdn.com/gblock Glenn Block
  • http://blogs.msdn.com/gblock Glenn Block

    Hi Joel

    That won’t give the desired behavior because it will wipe all the settings and only leave Bar. In this case I am pulling down the existing settings and modifying them with Bar which leaves the exiting settings in tact.

    As for why we can’t just do the foreach passing in the site, it is because Get-AzureWebsite without a name returns only summary information including the site name, status, and uri. This is because the API call is cheaper. When you specify the site name it gets all the details.

  • http://HuddledMasses.org Joel “Jaykul” Bennett

    Shouldn’t this:

    Get-AzureWebsite | ForEach-Object -Process {
    $site = Get-AzureWebsite $_.Name; $site.AppSettings["Bar"]=”Baz”;
    Set-AzureWebsite $_.Name -AppSettings $site.AppSettings}

    Just be this:
    Get-AzureWebsite | Set-AzureWebsite -AppSettings @{ “Bar” = “Baz” }

    I’m not 100% sure about that one, because I don’t have those cmdlets — but based on your syntax, I think that would work (you need to take advantage of the pipeline, not use ForEach-Object and create loops — loops are expensive, because you’re creating that cmdlet object every time, instead of just once) (P.S. where’s the download link? I installed the ones off github/WindowsAzure but it’s not there)

    The next example (with Start-Job) definitely doesn’t need the foreach…

  • http://twitter.com/ehexter Eric Hexter

    cool.. keep the powershell examples coming with the new updates!