Friday, July 10, 2015

PowerShell + Azure + Python : Use Project Custom Settings

Background

First to set up the background [bit reaching on the Dev side] on the post, quick introduction to what is an Azure Cloud service along with some terms Dev like to throw around:

Cloud Service :
PaaS offering , running VMs on Microsoft Azure. You have control over these VMs as you can remote into them and customize them to run your apps. A typical cloud service contains:

  • Web Role - Windows Server running IIS on top of it.
  • Worker Role - Windows Server.
Now using Visual Studio one can configure the Cloud Service as per ones need (Check Resources at the bottom). There are typically 2 files in your project definition which need tweaking (source : MSDN - link in Resources section) :


  • ServiceDefinition.csdef  : The service definition file defines the runtime settings for your cloud service including what roles are required, endpoints, and virtual machine size. None of the data stored in this file can be changed when your role is running.
  • ServiceConfiguration.cscfg : The service configuration file configures how many instances of a role are run and the values of the settings defined for a role. The data stored in this file can be changed while your role is running.







A full post on how to use Visual Studio to deploy a cloud service is out of scope for this post and me ;)

Task at hand

We were working on a Python project which will run on top of Azure utilizing cloud services (web and worker role). We had to customize our worker role a bit using the custom settings that could be defined for a Cloud project in Visual Studio. 

The customization needed us to read the custom settings defined in the Service Configuration file for the Azure Worker role and then consume it as per some logic.

The link at MSDN shows how to do it in C#, so I tried to port it to PowerShell.
It is relatively easy if you have been working with PS for a while.


Steps:


  1. Create a new Project in Visual Studio.

  2. Select Python Azure Cloud Service template to start with (need Python Azure SDK installed).

  3. After you create the Project from the template, it will ask you to select roles for your Cloud Service. I have added a Web & Worker role, this depends on your project. After that it asks you to select a Python environment, I chose a virtual environment for my Python app again this depends on your project.


  4. Now let's add a custom setting to our Worker role. Right click the Worker role > Properties. It will open up a configuration page like below:

  5. Now go to 'Settings' and click on 'Add Settings' button; go ahead and add the custom setting.



    Note - Adding a custom setting above will make an entry in the ServiceConfiguration.*.csfg files , see below :

  6. Before moving further and showing you how to access the custom setting in your code, it is important to understand the role PowerShell plays in configuring a Role.

    If you notice there is a bin directory under your each Role which contains PS scripts which configure your role e.g installing webpi, windows features etc and also take notice of a ps.cmd file which invokes these PowerShell script as a startup task.



    Take a look at the ServiceDefinition.csdef (which contains the runtime settings for my cloud service) and notice that it creates a startup task for the role.



    Below is the gist showing the ps.cmd batch file which calls our PowerShell Script, you can always modify it to fit the custom requirements you have, leaving up to you to direct Verbose stream to a log file (verbose stream used later):
  7. Now to the final piece in the puzzle , How to access the custom setting value and use it while configuring the Worker Role ?
    Well the example is already provided at the MSDN, Click here

    PowerShell to the rescue. Since PowerShell Script is already being used to configure a cloud service. One can put the extra few lines of code into the Script named ConfigureCloudService.ps1 to access the custom setting and make decisions or perform any action based on the value. You could also add another script and get it called from the ps.cmd of configurecloudservice.ps1 (you know how it works already).

    Easiest way is to load the DLL and then simply call the static method named GetConfigurationSettingValue on the RoleEnvironment Class.

I think it doesn't get easier than this, PowerShell gives us the capability to tap into the .NET framework, as a System Admin working on Microsoft realm it makes me more productive. Have you boarded the PS bandwagon yet ?

Resources:

Configuring an Azure Project
https://msdn.microsoft.com/en-us/library/azure/ee405486.aspx

How to: Configure the Roles for an Azure Cloud Service with Visual Studio
https://msdn.microsoft.com/en-us/library/azure/hh369931.aspx

5 comments:

  1. How to use config values from cloud.cscfg or local.cscfg in your Python script?

    extracting connection params to blob or table storage or queues etc?

    ReplyDelete
    Replies
    1. Probably read those values using PowerShell and generate a JSON object which can be fed as an input to the Python script.

      Delete
  2. i used this: http://stackoverflow.com/questions/34591436/azure-environment-variables-in-python-cloud-service thanks

    ReplyDelete
    Replies
    1. Cool, thanks for circling back and sharing the link :)

      Delete
    2. I've just realised your DLL answer is similar to the link from stackoverflow, but your answer came first, so credit to you my friend.

      they just added the bit about saving as an env value:
      [Environment]::SetEnvironmentVariable('settingname', $Setting)

      Delete