How to version an API in Azure API Management using Azure Resource Manager - api

When creating a new API in an Azure API Management Service using the portal, you can specify whether you would like the API to be versioned. However, I can't find a way to replicate this when creating an API in the Management service using ARM. Is this not currently supported, or am I missing something?
I have tried creating a versioned API in the portal and comparing the created template to the template of a non-versioned API and can't see a difference.
Thanks in advance.

To achieve this through ARM scripts you'll need to create an ApiVersionSet resource first:
{
"name": "[concat(variables('ManagementServiceName'), '/', variables('VersionSetName'))]",
"type": "Microsoft.ApiManagement/service/api-version-sets",
"apiVersion": "2017-03-01",
"properties": {
"description": "Api Description",
"displayName": "Api Name",
"versioningScheme": "Segment"
}
}
Then update the apiVersionSetId property on the Microsoft.ApiManagement/service/apis resource:
{
"type": "Microsoft.ApiManagement/service/apis",
"name": "[concat(variables('ManagementServiceName'), '/', variables('ApiName'))]",
"apiVersion": "2017-03-01",
"dependsOn": [
"[resourceId('Microsoft.ApiManagement/service/api-version-sets', variables('ManagementServiceName'), variables('VersionSetName'))]"
],
"properties": {
"displayName": "string",
"apiRevision": "1",
"description": "",
"serviceUrl": "string",
"path": "string",
"protocols": [
"https"
],
"isCurrent": true,
"apiVersion": "v1",
"apiVersionName": "v1",
"apiVersionDescription": "string",
"apiVersionSetId": "[concat('/api-version-sets', variables('VersionSetName'))]"
}
}

resource for the api-version-sets
"name": "my-api-version-sets",
"type": "api-version-sets",
"apiVersion": "2018-01-01",
"properties": {
"displayName": "Provider API",
"versioningScheme": "Segment"
},
"dependsOn": [
"[concat('Microsoft.ApiManagement/service/', variables('apiManagementServiceName'))]"
]
Then other to apis
"apiVersion": "2018-01-01",
"type": "apis",
"properties": {
....
"isCurrent": true,
"apiVersion": "v1",
"apiVersionSetId": "/api-version-sets/my-api-version-sets"

You can specify the version on Azure ARM portal in path,header or as a query string.But the old azure API management portal not support in build versioning.Any way you can specify the versioning in Web API URL suffix.
Still if you have any issue kindly add some image and describe your issue.
Azure ARM Portal (New APIM)
Azure APIM Portal (OLD)
Thanks,
Infaaz

Related

Schema evolution when adding new field

Imagine there are to separate apps: producer and consumer.
The code of producer:
import os
from confluent_kafka import avro
from confluent_kafka.avro import AvroProducer
avsc_dir = os.path.dirname(os.path.realpath(__file__))
value_schema = avro.load(os.path.join(avsc_dir, "basic_schema.avsc"))
config = {'bootstrap.servers': 'localhost:9092', 'schema.registry.url': 'http://0.0.0.0:8081'}
producer = AvroProducer(config=config, default_value_schema=value_schema)
producer.produce(topic='testavro', value={'first_name': 'Andrey', 'last_name': 'Volkonsky'})
basic_schema.avsc file is located within producer app. Its content:
{
"name": "basic",
"type": "record",
"doc": "basic schema for tests",
"namespace": "python.test.basic",
"fields": [
{
"name": "first_name",
"doc": "first name",
"type": "string"
},
{
"name": "last_name",
"doc": "last name",
"type": "string"
}
]
}
For now it does not matter what's inside consumer.
We run producer once and everything is ok. Then I want to add age field:
basic_schema.avsc:
{
"name": "basic",
"type": "record",
"doc": "basic schema for tests",
"namespace": "python.test.basic",
"fields": [
{
"name": "first_name",
"doc": "first name",
"type": "string"
},
{
"name": "last_name",
"doc": "last name",
"type": "string"
},
{
"name": "age",
"doc": "age",
"type": "int"
}
]
}
Here I got error:
confluent_kafka.avro.error.ClientError: Incompatible Avro schema:409
They say here https://docs.confluent.io/platform/current/schema-registry/avro.html#summary that for compitability type == BACKWARD consumers should be updated first.
I cannot understand technically. I mean do I have to copy basic_schema.avsc file to consumer
and run it?
If you registered schema with BACKWARDS compatibility (the default), confluent schema registry simply wont allow you to make an incompatible change - adding a mandatory field.
you can add optional field or use forward compatibility
the rules about what should be upgraded first is correct regardless of what changes the compatibility rule actually allows you to make.
edit - additional info
don't use forward compatibility simply because you might have a need to add mandatory fields. Use the compatibility that makes sense for your case based on who can update first e.g. it may be impossible to make all producers upgrade at the same time.
so if using backwards compatibility AND need to add a mandatory field, you probably need a new version of the service e.g. topic.v1 and topic.v2 where v2 of the service uses the schema with the new mandatory field and you can deprecate v1 service...for example

How to get a VM Flavours in IBM cloud through Softlayer Rest API

I want to get a VM Flavours(Compute C1.2x2, Balanced B1.2x8) using Softlayer Rest API. I didn't find any API references related to get Flavours.
To retrieve the active VM flavors use the following rest api call:
Method: GET
https://[username]:[apiKey]#api.softlayer.com/rest/v3/SoftLayer_Product_Package/835/getActivePresets
You will get a response like the below example:
[
{
"description": "B1.16x64x100",
"id": 351,
"isActive": "1",
"keyName": "B1_16X64X100",
"name": "B1.16x64x100",
"packageId": 835
},
{
"description": "C1.1x1x100",
"id": 359,
"isActive": "1",
"keyName": "C1_1X1X100",
"name": "C1.1x1x100",
"packageId": 835
},
]

How do I automate adding a custom Iot Hub Endpoint (and route to it)?

In order to receive Azure IotHub Device Twin change notifications, it appears that it's necessary to create a custom endpoint and create a route to send notifications to that endpoint. This seems straightforward enough on the Azure Portal, but as one might expect we want to automate it.
I haven't been able to find any documentation for the the az cli or even the REST API, though I might have missed something. I didn't find anything promising looking in the SDKs either.
How do I automate adding a custom endpoint and then setting up the route for device twin notifications?
You can check IotHubs template to see if it helps.
Route:
"routing": {
"endpoints": {
"serviceBusQueues": [
{
"connectionString": "string",
"name": "string",
"subscriptionId": "string",
"resourceGroup": "string"
}
]
},
"routes": [
{
"name": "string",
"source": "string",
"condition": "string",
"endpointNames": [
"string"
],
"isEnabled": boolean
}
],
Consumer group:
{
"apiVersion": "2016-02-03",
"type": "Microsoft.Devices/IotHubs/eventhubEndpoints/ConsumerGroups",
"name": "[concat(parameters('hubName'), '/events/cg1')]",
"dependsOn": [
"[concat('Microsoft.Devices/Iothubs/', parameters('hubName'))]"
]
},
For more detailed information you can reference:
Microsoft.Devices/IotHubs template reference
Create an IoT hub using Azure Resource Manager template (PowerShell)

ARM - How can I get the access key from a storage account to use in AppSettings later in the template?

I'm creating an Azure Resource Manager template that instantiates multiple resources, including an Azure storage account and an Azure App Service with a Web App.
I'd like to be able to capture the primary access key (or the full connection string, either way is fine) from the newly-created storage account, and use that as a value for one of the AppSettings for the Web App.
Is that possible?
Use the listkeys helper function.
"appSettings": [
{
"name": "STORAGE_KEY",
"value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]"
}
]
This quickstart does something similar:
https://azure.microsoft.com/en-us/documentation/articles/cache-web-app-arm-with-redis-cache-provision/
The syntax has changed since the other answer was accepted. The error you will now hit is 'Template language expression property 'key1' doesn't exist, available properties are 'keys'
Keys are now represented as an array of keys, and the syntax is now:
"StorageAccount": "[Concat('DefaultEndpointsProtocol=https;AccountName=',variables('StorageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]",
See: http://samcogan.com/retrieve-azure-storage-key-in-arm-script/
I faced with this issue two times. First in the 2015 and last today in May of 2017.
I need to add connection strings to the WebApp - I want to add strings automatically from generated resources during deployment from the ARM template. It can help later to not add manually this values.
First time I used old version of the function listKeys (it looks like old version returns result not as object but as value):
"AzureWebJobsStorage": {
"type": "Custom",
"value": "[concat(variables('storageConnectionString'), listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2015-05-01-preview').key1)]"
},
Today last version of the working template is:
"resources": [
{
"apiVersion": "2015-08-01",
"type": "config",
"name": "connectionstrings",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites/', parameters('webSiteName'))]"
],
"properties": {
"DefaultConnection": {
"value": "[concat('Data Source=tcp:', reference(resourceId('Microsoft.Sql/servers/', parameters('sqlserverName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('databaseName'), ';User Id=', parameters('administratorLogin'), '#', parameters('sqlserverName'), ';Password=', parameters('administratorLoginPassword'), ';')]",
"type": "SQLServer"
},
"AzureWebJobsStorage": {
"type": "Custom",
"value": "[concat(variables('storageConnectionString'), listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2016-01-01').keys[0].value)]"
},
"AzureWebJobsDashboard": {
"type": "Custom",
"value": "[concat(variables('storageConnectionString'), listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2016-01-01').keys[0].value)]"
}
}
},
Thanks.
below is example for adding storage account to ADLA
"storageAccounts": [
{
"name": "[parameters('DataLakeAnalyticsStorageAccountname')]",
"properties": {
"accessKey": "[listKeys(variables('storageAccountid'),'2015-05-01-preview').key1]"
}
}
],
in variable you can keep
"variables": {
"apiVersion": "[providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]]",
"storageAccountid": "[concat(resourceGroup().id,'/providers/','Microsoft.Storage/storageAccounts/', parameters('DataLakeAnalyticsStorageAccountname'))]"
},

google plus api, people search by location

I'm looking for documentation on how to format a query for the Google Plus People search API. Specifically how to search by location, in addition to using keywords.
I would also be great to know how to search for keywords with AND OR logic.
Unfortunately there is currently no way to do this. Google Plus People Search searches on displayName
You can test this by going to the bottom and using the try me:
GET https://www.googleapis.com/plus/v1/people?query=denmark&key={YOUR_API_KEY}
Authorization: Bearer ya29.yQAdQCMab-MuerpNcx-dImbA0fBPxfsJbzYo9W0zA2rPKxG0oSNOh9MlarI9BD2EhVAQLHQiqdsWNg
X-JavaScript-User-Agent: Google APIs Explorer
200 OK
- Show headers -
{
"kind": "plus#peopleFeed",
"etag": "\"RqKWnRU4WW46-6W3rWhLR9iFZQM/CQs9-i31YgOHOFErObqjjPpqvac\"",
"selfLink": "https://content.googleapis.com/plus/v1/people?query=denmark&key=AIzaSyCFj15TpkchL4OUhLD1Q2zgxQnMb7v3XaM",
"title": "Google+ People Search Results",
"nextPageToken": "EBkaAA",
"items": [
{
"kind": "plus#person",
"etag": "\"RqKWnRU4WW46-6W3rWhLR9iFZQM/dvmOjlS_L11y3FImcrvga14_MPI\"",
"objectType": "page",
"id": "107491210485921364379",
"displayName": "Denmark.dk - The official website of Denmark",
"url": "https://plus.google.com/+denmark",
"image": {
"url": "https://lh4.googleusercontent.com/-mBlKA4p0ZYQ/AAAAAAAAAAI/AAAAAAAAAOE/PxZ_m7uQ1LM/photo.jpg?sz=50"
}
},
{
"kind": "plus#person",
"etag": "\"RqKWnRU4WW46-6W3rWhLR9iFZQM/wAHGx7MwIQSVIJftHeGgFMiK7Uc\"",
"objectType": "person",
"id": "102142746546626575404",
"displayName": "Alumeco Denmark",
"url": "https://plus.google.com/102142746546626575404",
"image": {
"url": "https://lh6.googleusercontent.com/-L9Tg78K2IVU/AAAAAAAAAAI/AAAAAAAAAsU/qaJ2thgrfio/photo.jpg?sz=50"
}
}}
As you can see it is returning people who have Denmark in there display name. A feature request has been made for this. https://code.google.com/p/google-plus-platform/issues/detail?id=693