Tuesday, July 25, 2017

Discrepancies in Azure service models and APIs

Different Azure services uses difference models of consumption. This post aims to list down those differences. Below are the categories where we can see differences.
  • Service naming model
    • Unique name inside Azure
    • Unique name inside subscription
  • API URL pattern
    • Instance specific URL
      • Instance name as sub domain
      • Service instance name in URL path
    • Generic URL
  • API authorization.
    • Key - Azure Search
    • Time limited tokens - Translator Text API
  • Passing API authorization
    • Inside URL as query string
    • Inside http headers

Service naming model

This refers to how we create the Azure service. There are mainly 2 types unique in the entire Azure v/s unique in subscription

Unique name inside Azure

Most of the services require us to create a globally unique name. That name will often end up as sub domain or part of URL. 

eg: Storage account

The problem with this mechanism is creation of new service instance from the application on the fly. For example, assume we are offering a SaaS solution and database isolation is one DB / tenant. There is a limit of 5000 databases per Azure SQL Server. When our 5001 tenant registers, we have to create next SQL Server instance from the program. Since the server name has to be unique across entire Azure, our program has to do trial and error methods to get unique name. To workaround this problem, we can take different routes such as generating GUID, create instances upfront etc... But it is something to be considered during the development process. Else it just fails.

Unique name in Subscription

Others end up in creating a name which is unique across the subscription.The AppInsight is the example for such a service.

API URL Pattern

All most all the services are designed to be consumed via http(s) web service endpoints. Mainly ReST based APIs with JSON data format. The URL pattern differs per service. Some service demand URL with its name and some can be accessed using generic URL.

Instance specific URL

Here the name of the service instance is needed in the API URL as sub domain or in the path.

Instance name as sub domain

The Azure storage account is one example for a service which demands globally unique name which ends up as sub domain.

Eg: https://<storage account>.blob.core.windows.net/ 

The services such as WebApps really demands the URL separation using sub domain.

Service instance name in URL path

If we look at some services we can see the service name is appearing inside the URL path after the domain.

eg: Analysis service  asazure://westus.asazure.windows.net/<analysisservicename>

Generic URL

In this category, there won't be any URL which has the service name in it. Instead they use a generic URL to hit the Azure service and identify service via parameters. Parameters can be request headers containing API keys or tokens.

eg: Application Insights

API Authorization

Authentication & authorization are essential factors in web service based API world. There are 2 different methods we can see in Azure services.

Key based

Key is same as in real world. The key can be used multiple times, until the lock is replaced. Similarly in Azure world, the validity of key is till that key is replaced. If anyone obtain our key, they can keep  using our service till we identify the theft and replace.

eg: Azure search. It demands us to put the key in the header.

Token based

In simple sense, token are short lived keys. Using a key or some other mechanism, we can create a token and use it for predefined time. Once it expires we have renew the token. Tokens has better security but difficult to use.

eg: Text Translator API. Details available here on how to use from Postman.

Passing API Authorization

Another area is how we can pass the authorization whether it is key or token

Inside URL as QueryString

Some services accept the authorization via the URL in the form of query string. 

Inside http headers

Other services needs the authorization in the header. eg: Translator Text API

More categories

API Version

Some services such as Azure Search needs version in the API. The versioning is in the form of date 
eg:https://<search service>.search.windows.net/indexes/<index>/docs?api-version=2016-09-01&search=<search key>&highlight=content

But the Translator Text follows v# versioning eg:https://api.microsofttranslator.com/v2/Http.svc/GetTranslations?text=jaguar&from=en&to=es&maxTranslations=5

Another way we can find for versioning is in Storage. It demands the version inside the http headers. Refer for details. Also it needs version as x-ms-version header.

Some random thoughts

Ideally as per the API guidelines (even from Microsoft) all the APIs which an application or platform provides should follow same standards. They should look like all are designed by same person. That way, consumers don't have to invest much time learning the APIs and usage. 

But in case of Azure, we cannot proceed with that principle. We have to learn to use different services separately. Why Microsoft Azure service APIs has this discrepancy?

We cannot assume that the teams who designed & developed APIs don't know this basic principle of API design. They should be having their own reasons why they did so. If we look at the Translator Text API, may be team thinks that, it should be really protected using auto expiring tokens where the Azure search team thought, search results are less secure and just needs to be protected by a key. May be from consumers point we value our search result data more than a generic translation method.

Another reason might be legacy code. Means connecting legacy code and putting into production may end up in having different API models. Also if a product is bought from other company via acquisition or so, it may end up differently. At the end the time to market matters which is nothing but money. Sometimes when weighing the money we will get due to fast release v/s beautifying the API, money gets priority. 

Competition matters here too. Sometimes first-mover strategy gives a big advantage and it may lock in clients.

Whatever the case, it seems there are no design notes publicly available describing the rationale behind these different decisions similar to Angular. We have to take our best guess why it is so and learn it. 

Tuesday, July 18, 2017

Azure Cognitive Services - Translator Text API - Calling from Postman

Azure cognitive service suit offers a lot of different APIs. One if it is language translation. It is named as Translator Text API. The good point is that it is offered as freemium meaning there is a free tier.

Calling the Translator API

Since it is service it is offered as web service. There are so many samples to use this service from different languages such as C#, JavaScript, PHP etc... which are available in their GitHub repo. But there is tutorial how can we simply call it from Postman which is web developers best friend to consume APIs.

Steps

Unlike many other APIs, this involves 2 step process. Steps given below
  1. Get the token from Azure using STS url which is currently https://api.cognitive.microsoft.com/sts/v1.0/issueToken. This URL is present in Azure portal when we navigate to Translate service instance. This may change in future.
    1. Calling this URL has to be POST with "Ocp-Apim-Subscription-Key" in the header. The value for this header is the keys present in Azure portal.
    2. The result of this call will give us a short lived token which has to be used in next step
    3. Once the token expires, we have to get renew. 10 mins is the expiry.
  2. Now using the token we can call the real, web service located at below URL
    1. https://api.microsofttranslator.com/v2/Http.svc
    2. This method accepts some parameters a query string and some parameters via POST / request data.

Example

Below goes the screenshots. 

Getting Translator Text API Keys from Azure portal. Image credits to MSDN Blogs. This key is used in next step to get token.

The above screenshot shows how to call token service from Postman to get the short lived token used for actual API call. The Ocp-Apim-Subscription-Key should be kept secret as it will help others to use our quota. It has to be changed explicitly if it is leaked.

The above image shows the real Translator Text API call. API needs the token obtained in the previous step. The token has to be prefixed with Bearer and a space before using in this call via Authorization header.
This API accepts required parameter in a hybrid way. Some are in the query string and some can be in optional POST request.
Make sure the optional post request body is properly formatted. One such format is given below.

If the POST request body has any format mismatch the request will be rejected by the server.

Happy posting...

References & more reading

https://blogs.msdn.microsoft.com/data_otaku/2016/11/05/goofing-around-with-the-cognitive-services-translator-api/
https://dev.cognitive.microsoft.com/docs/services/57346a70b4769d2694911369/operations/57346edcb5816c23e4bf7421
https://msdn.microsoft.com/en-us/library/ff512423.aspx

Tuesday, July 4, 2017

Adding Azure VM auto shutdown via ARM template

This post is intended to show how can we use a simple Azure feature via ARM template. The feature is 'scheduled shutdown of virtual machines'. It is useful when we play with machines. Seriously, never shutdown production machines unless there is a real business scenario such as your business is strictly running during a particular time and you don't want to keep the system open for hackers to play with. eg: day trading.

Before we go ahead, this article doesn't promote the use of virtual machines. Virtual machines which is in cloud terms 'Infrastructure as a Service' is the last to consider when we design for cloud. One, it is costly. It is not truly pay as use mode. Virtual machines have to run regardless there is workload or not. We have to pay for all these idle times. Also virtual machines take more time to scale out as the boot time is more. By the time, the spike in requests/workload might be over. But there would be scenarios where we have to use VMs. When we deal with older systems without enough budget to rewrite, we have to go for VMs. Also when our corporate IT is not believing in PaaS because of security, VM is the option.

Now coming to the point. Auto shutdown can easily be done from portal as shown in the announcement. There are some sites out there which explains how to setup auto shut down via ARM. This is my experience with the same.

The schema of ARM template can be found in the below link. It is the starting point.
https://docs.microsoft.com/en-us/azure/templates/microsoft.devtestlab/schedules

Sample ARM template to shutdown

Below goes JSON to set auto shutdown to a VM
{
      "apiVersion": "2017-04-26-preview",
      "type": "Microsoft.DevTestLab/schedules",
      "name": "shutdown-computevm-nanotest",
      "location": "[resourceGroup().location]",
      "properties": {
        "status": "Disabled",
        "timeZoneId": "Pacific Standard Time",
        "taskType": "ComputeVmShutdownTask",
        "notificationSettings": {
          "status": "Disabled",
          "timeInMinutes": 15,
          "webhookUrl": "http://joymononline.in"
        },
        "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', parameters('nanoName'))]",
        "dailyRecurrence": {
          "time": "1600"
        }
        //"hourlyRecurrence": {
        //  "minute": "1"
        //}
      }
    }
We can see webHookUrl is given to a dummy url and hourlyRecurrence is commented. Lets see the details.

Where to add this JSON fragment in ARM template

This is not a sub resource of VM mode. Rather this needs to be directly added into top level resources node in ARM template.

Can we shutdown VM hourly

If we are using an Azure subscription which credits 50$ per month, it is not good to set auto shutdown daily one. As soon as we are done with the VM, it should be shutdown. Even if we forget, it has to shutdown. But currently the feature doesn't support hourly recurrence though the schema supports. That is why it is commented.

Can we omit daily recurrence value?

Below is the error which will pop when we don't give value for daily recurrence. Notice that this error won't be displayed during validation. But throws when we execute ARM template with ARM manager in Azure.

17:48:25 - [ERROR] Microsoft.DevTestLab/schedules 'autoShutDownPolicy' failed with message '{
17:48:25 - [ERROR]   "error": {
17:48:25 - [ERROR]     "code": "MissingRequiredProperty",
17:48:25 - [ERROR]     "message": "Missing required property DailyRecurrence."
17:48:25 - [ERROR]   }
17:48:25 - [ERROR] }'

What is big deal with the name

Below is the error receive when a pet name given to schedule. Again notice that validation don't show but execution throws. In other words its runtime error.

17:55:49 - [ERROR] New-AzureRmResourceGroupDeployment : 5:55:49 PM - Resource
17:55:49 - [ERROR] Microsoft.DevTestLab/schedules 'autoShutDownPolicy' failed with message '{
17:55:49 - [ERROR]   "error": {
17:55:49 - [ERROR]     "code": "InvalidScheduleId",
17:55:49 - [ERROR]     "message": "The schedule should be created in subscription
17:55:49 - [ERROR] 11111111-1111-1111-8888-####ffffeeee, resource group <Storage>
17:55:49 - [ERROR] and with name shutdown-computevm-nanotest."
17:55:49 - [ERROR]   }

The nanotest is the VM name.

APIVersion and region

The sample template above shows apiVersion of schedules '2017-04-26-preview'. It is region specific. Not all regions supporting all API versions. This is again an runtime error. Validation will pass.

There is a URL which tells what are available in what region. There are some programmatic techniques to find out the API version and other details.

The good part is that the error is descriptive, telling us what API version to use. That is really useful.

Rolling back ARM deployment

As mentioned above some errors happen when we deploy/execute ARM template. If the auto shutdown setup fails, does it revert the VM deployment? As software engineers we assume that it will,  same as MSI deployment or there will be some flags to deploy ARM in transaction. But it never roll backs. It is our pain to clean up what is left after a partially failed ARM deployment. Feature request below. It is there for the last one year.

https://feedback.azure.com/forums/281804-azure-resource-manager/suggestions/13701420-rollback-template-deployment-if-anything-fail-ju

The suggestion is to make our ARM template deployment idempotent. Simply saying even if we redeploy, it should not cause any harm. It should run many times by producing same result as first run. Simple if we are just setting up architecture via ARM. Gets complex if there are custom scripts running as part of deployment.

Debug ARM template

For a simple feature to get working, we may encounter these many errors. As developers we might have started thinking how to debug the ARM templates. In general the error messages are meaningful, if we are familiar with Azure terms. Debugging ARM template itself has scope for separate post. Again, it gets complicated when ARM template uses custom scripts. Below are 2 links talking about troubleshooting ARM template deployments.