Creating CosmosDB with Terraform

Steve Dillon
3 min readJan 14, 2021

In this continuing series of articles about using Terraform to create infrastructures in Azure we are going to look at CosmosDB. In our prior work, we created Application Insights, Log Analytics and KeyVault as cornerstone Azure infrastructure, we only need to look at the CosmosDB pieces in this article.

The code referenced here is in terraform-azurerm-samples/samples/scenarios/03-cosmosdb.

We will need to create 3 items in a hierarchy

  1. A CosmosDB account, this sets some global parameters for all databases.
  2. A CosmosDB Database. In our case we set a autoscale provisioning for all containers. The containers share this provisioning and we don’t individually provision Resource Units at the container level.
  3. A CosmosDB Container. This is a ‘table’ that belongs to the before Database and Account.

Create a CosmosDB Account

Parameters for calling CosmoDB module

Parameters of interest:

  • Source: There are two cosmosDB ‘endpoint’ options. We generally refer to high level items as Endpoints for consistency in our library. We have 2 endpoints. The base endpoint creates an account and returns an access key as an output for the account created. The secure endpoint calls the base module, but then stores the access key in Azure Key Vault. The less passing around of secrets in Terraform, the less chance of them being revealed.
  • context and observability_settings, are standard items in the Terraform-Azurerm library. Look at prior articles discussing them.
  • service_settings: tier (offer_type) can only be ‘Standard’ at this time. kind can be ‘GlobalDocumentDB’ or ‘MongoDB’, we use GlobalDocumentDB. consistency_level is part of the consistency_policy, and can take any of the values the resource specifies.

Behind The Curtain:

The workings of this module are in terraform-azurerm/services/cosmos-db/endpoint/dual/base/main.tf and creates an azurerm_cosmosdb_account

The code shows a real example of using the azurerm_cosmosdb_account.

Create a CosmosDB Database

Just a few lines of code to create a database. In our case we just provision an Autoscaling Database with a stated maximum capacity.

The Backing code that implements this in the azurerm_cosmosdb_sql_database resource:

Create a CosmosDB Container

Criticizing our own Code

Looking at the last example, to create a Container in a database, our module fails the the test of ‘Doing something useful’. The module just serializes all the parameters of azurerm_cosmosdb_sql_container into an object, and then deserializes the object to pass them to azurerm_cosmosdb_sql_container.

I know why this happened, because we try to never allocate an Azure resource in our main code, but strive to create all resources in the terraform-azurerm library. In that noble goal, we have created a facade wrapper to azurem_cosmosdb_sql_container.

I know what I would like to do to improve the usefulness of this wrapper. It should take a map<tablename, partition_key_path> which are the only parameters that change on a per table basis. Using the Module-ForEach feature of terraform 0.13 and above, we could allocate all of our containers in one module call. (CosmosDB module was written before Module ForEach).

Wrapping Up

Again, thanks for reading, Hope this helps with whatever brought you here.

Steve

--

--

Steve Dillon

Cloud Architect and Automation specialist. Specializing in AWS, Hashicorp and DevOps.