Creating Cosmos DB Resources using ARM Templates

This week we saw a significant update to the ARM template for Cosmos DB, which now allows us to create databases and containers. Up until now, we've only been able to create Cosmos DB accounts using templates, we then had to create the databases, containers, tables etc. through PowerShell or the portal etc.

With this update, we are now able to deploy much more of our Cosmos setup with ARM templates, including databases, containers, graphs, namespaces and tables. However, there are still some components we can't create with templates yet:

  • User Defined Functions
  • Stored Procedures
  • Triggers

Hopefully these will come along soon but for now, your still going to need to create them using a different method.

I've also updated the Azure Resource Manager Snippets for VS Code today to incorporate these new templates, to make it even easier to create these templates. If you don't have this installed, I recommend you take a look.

Let's take a look at creating the resource we can create with a template.

Account

The first thing we need to create when deploying Cosmos DB instances is the account. This is nothing new, as we've been able to use ARM templates for this for a while, but obviously, we can't define anything else without it.

The account is where we define the following database properties:

  • Location (or locations if you wish to geo-replicate)
  • Consistency Policy
  • Failover
  • Multiple Write locations

We're going to create a DB in 2 locations, using eventual consistency, automatic failover and multiple write locations.

{
  "type": "Microsoft.DocumentDB/databaseAccounts",
  "apiVersion": "2015-04-08",
  "name": "[variables('accountName')]",
  "location": "[resourceGroup().location]",
  "tags": {},
  "kind": "GlobalDocumentDB",
  "properties": {
    "consistencyPolicy": {
      "defaultConsistencyLevel": "Eventual",
      "maxStalenessPrefix": 1,
      "maxIntervalInSeconds": 5
    },
    "locations": [
      {
        "locationName": "West Europe",
        "failoverPriority": 0
      },
      {
        "locationName": "East US 2",
        "failoverPriority": 1
      }
    ],
    "databaseAccountOfferType": "Standard",
    "enableAutomaticFailover": true,
    "enableMultipleWriteLocations": true
  }
}

Database

Now we have an account setup we can create a database (or multiple databases). In the database template, we are going to define:

  • The database name
  • The throughput (RUs) for the database

The database is also going to define the type of database you want, SQL, Gremlin, Cassandra and Table Storage. The type is defined as part of the name property, so in the example below we are looking at SQL:

"name": "[concat(variables('accountName'), '/sql/', parameters('databaseName'))]"

If we wanted to use Gremlin instead it would look like this:

"name": "[concat(variables('accountName'), '/gremlin/', parameters('databaseName'))]",

The full JSON for our SQL DB is below:

    {
            "type": "Microsoft.DocumentDB/databaseAccounts/apis/databases",
            "name": "[concat(variables('accountName'), '/sql/', parameters('databaseName'))]",
            "apiVersion": "2016-03-31",
            "dependsOn": [ "[resourceId('Microsoft.DocumentDB/databaseAccounts/', variables('accountName'))]" ],
            "properties":{
                "resource":{
                    "id": "[parameters('databaseName')]"
                },
                "options": { "throughput": "[parameters('throughput')]" }
            }
        },

Container

As we're using the SQL API, the next thing we need to deploy is a container. If you were using an alternative API, you would define things like a Graph for Gremlin, or a Namespace for Cassandra instead. You can see examples for all of these in the quick start templates and the VS Code Snippets.

Here we define:

  • Container Name
  • Partition Key
  • Indexing Mode & Paths
     {
            "type": "Microsoft.DocumentDb/databaseAccounts/apis/databases/containers",
            "name": "[concat(variables('accountName'), '/sql/', parameters('databaseName'), '/', parameters('container1Name'))]",
            "apiVersion": "2016-03-31",
            "dependsOn": [ "[resourceId('Microsoft.DocumentDB/databaseAccounts/apis/databases', variables('accountName'), 'sql', parameters('databaseName'))]" ],
            "properties":
            {
                "resource":{
                    "id":  "[parameters('container1Name')]",
                    "partitionKey": {
                        "paths": [
                        "/MyPartitionKey1"
                        ],
                        "kind": "Hash"
                    },
                    "indexingPolicy": {
                        "indexingMode": "consistent",
                        "includedPaths": [{
                                "path": "/*",
                                "indexes": [
                                    {
                                        "kind": "Range",
                                        "dataType": "number",
                                        "precision": -1
                                    },
                                    {
                                        "kind": "Range",
                                        "dataType": "string",
                                        "precision": -1
                                    }
                                ]
                            }
                        ],
                        "excludedPaths": [{
                                "path": "/MyPathToNotIndex/*"
                            }
                        ]
                    }
                }
            }
        },

Deploy

Now we have defined our account, database and container, we can deploy this like any other ARM template, and we'll get a fully provisioned Cosmos DB instance that is ready to use.

Image Attribution

M33, the Triangulum Galaxy, on September 28th, 2014 flickr photo by Tycho's Nose shared under a Creative Commons (BY-NC-ND) license