How to Extend the Command Line Tools in the Windows Azure SDK for PHP

June 7, 2012 update: The Microsoft Windows Azure team has released a new Windows Azure SDK for PHP. This release is part of an effort to keep PHP client libraries up to date with new Windows Azure features and to make PHP a first-class citizen in Windows Azure. The latest client libraries are on GitHub: https://github.com/WindowsAzure/azure-sdk-for-php. While the SDK hosted on CodePlex will continue to work for the foreseeable future, it is strongly recommended that new PHP/Windows Azure application use the SDK hosted on GitHub.

The work done by Maarten Balliauw and other contributors in building the SDK hosted on CodePlex was critical in unifying the PHP developer experience for Windows Azure. The Windows Azure team is grateful to these contributors for their pioneering work and looks forward to their continued support (and yours!) in adding to the new SDK on GitHub.

Thanks,

      
The Windows Azure Team


I’ve been spending quite a bit of time exploring the command line tools for the Windows Azure SDK for PHP. As I’ve done so, I found that I needed to add functionality in some areas (essentially, I needed the ability to access role instance properties). What I want to share in this post is just how easy it was to extend the command line tools.

The first thing to understand about the Windows Azure SDK for PHP command line tools is that the functionality for each tool is defined in the classes in the \library\Microsoft\WindowsAzure\CommandLine directory:

image

(The .bat and .sh files that are actually called at the command line are essentially wrappers for these classes and can be found in the \bin directory.) The key to easily extending command line functionality is that each of these classes extends the Microsoft_Console_Command class (read Maarten Balliauw’s post A hidden gem in the Windows Azure SDK for PHP: command line parsing for more information about how this works). So, to add functionality for getting role instance properties, I just needed to add an appropriately decorated method to the Deployment class:

 /**
  * Get role instance properties.
  * 
  * @command-name GetRoleInstanceProperties
  * @command-description Get role instance information for a specified role instance.
  * @command-parameter-for $subscriptionId Microsoft_Console_Command_ParameterSource_Argv|Microsoft_Console_Command_ParameterSource_ConfigFile|Microsoft_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
  * @command-parameter-for $certificate Microsoft_Console_Command_ParameterSource_Argv|Microsoft_Console_Command_ParameterSource_ConfigFile|Microsoft_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
  * @command-parameter-for $certificatePassphrase Microsoft_Console_Command_ParameterSource_Argv|Microsoft_Console_Command_ParameterSource_ConfigFile --Passphrase|-p The certificate passphrase. If not specified, a prompt will be displayed.
  * @command-parameter-for $serviceName Microsoft_Console_Command_ParameterSource_Argv|Microsoft_Console_Command_ParameterSource_ConfigFile|Microsoft_Console_Command_ParameterSource_Env|Microsoft_Console_Command_ParameterSource_StdIn --Name Required. The hosted service DNS name to operate on.
  * @command-parameter-for $deploymentSlot Microsoft_Console_Command_ParameterSource_Argv|Microsoft_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
  * @command-parameter-for $deploymentName Microsoft_Console_Command_ParameterSource_Argv|Microsoft_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
  * @command-parameter-for $instanceName Microsoft_Console_Command_ParameterSource_Argv|Microsoft_Console_Command_ParameterSource_ConfigFile --InstanceName Required. The role instance name to retrieve properties for.
  * @command-example Get role instance properties for role "role_0" for production-slot deployment of the hosted service "phptest":
  * @command-example GetRoleInstances -sid="<your_subscription_id>" -cert="mycert.pem"
  * @command-example --Name="servicename" --BySlot="production" --InstanceName="role_0"
  */
     public function getRoleInstanceProperties($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $instanceName)
     {
         $client = new Microsoft_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
         
         $result = null;
         
         if (!is_null($deploymentSlot) && $deploymentSlot != '') {
             $deploymentSlot = strtolower($deploymentSlot);
             
             $result = $client->getRoleInstancesByDeploymentSlot($serviceName, $deploymentSlot);
         } else {
             $result = $client->getRoleInstancesByDeploymentId($serviceName, $deploymentName);
         }
         
         $instance_found = false;
         
         foreach($result as $instance) {
             if($instance['instancename'] == $instanceName) {
                 printf("Status: \t%s\n", $instance['instancestatus']);
                 printf("Upgrade domain: %s\n", $instance['instanceupgradedomain']);
                 printf("Fault domain: \t%s\n", $instance['instancefaultdomain']);
                 printf("Size: \t\t%s\n", $instance['instancesize']);
                 printf("\n");
                 $instance_found = true;
                 continue;
             }
         }
         
         if(!$instance_found) {
                 printf("No instance with name %s was found.", $instanceName);
         }
     }

Pay close attention to the comments on the method – it’s the comments that allow the Microsoft_Console_Command class to do its magic. And, if you look closely, you’ll see that I call two methods on the $client object (getRoleInstancesByDeploymentSlot and getRoleInstancesByDeploymentId). I had to add those methods to the Microsoft_WindowsAzure_Management_Client class (which was easy to do by using the existing methods as models). Here’s the getRoleInstancesByDeploymentSlot class:

 /**
  * The Get Role Instances by Deployment Slot operation returns an array of arrays containing role instance information
  * for each role instance associated with the deployment specified by slot (staging or production).
  * 
  * @param string $serviceName The service name. This is the DNS name used for production deployments.
  * @param string $deploymentSlot The deployment slot (production or staging)
  * @return Array
  * @throws Microsoft_WindowsAzure_Management_Exception
  */
     public function getRoleInstancesByDeploymentSlot($serviceName, $deploymentSlot)
     {
         if ($serviceName == '' || is_null($serviceName)) {
             throw new Microsoft_WindowsAzure_Management_Exception('Service name should be specified.');
         }
         $deploymentSlot = strtolower($deploymentSlot);
         if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
             throw new Microsoft_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
         }
         
         $operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
         $deployment = $this->_getDeployment($operationUrl);
         return $deployment->roleInstanceList;
     }

 

That’s it. Typing deployment at the command line shows that my new getiroleinstanceproperties operation is now part of the deployment tool.

image

So, in summary, to add operations to a command line tool: Add a method to the class in the \library\Microsoft\WindowsAzure\CommandLine directory that corresponds to the command line tool you want to extend. Be sure to appropriately comment the method (as shown above or explained in this post). Depending on what your added method does, you may have to add functionality to other classes in the SDK.  Of course, after you are done, submit your work as a patch! (I’m in the process of doing that now.)

-Brian

Share this on Twitter