Coder Perfect

Bicep is used to deploy UserDefinedFunction in conjunction with Azure Cosmos DB.

Problem

Is it feasible to use bicep to deploy a stored procedure or user defined function in conjunction with the Azure CosmosDB SQL API?

I’m aware that using the directly arm template https://github.com/Azure/azure-quickstart-templates/blob/master/quickstarts/microsoft.documentdb/cosmosdb-sql-container-sprocs/azuredeploy.json is feasible.

I couldn’t find any documentation on performing this in the biceps, so I did it on my own. I attempted to construct the bicep resource in the same manner as any other e.g. container, however there were always exceptions, such as:

Deployment failed. Correlation ID: 736b1c6e-fec7-479c-88e5-5a8034eac762. {
  "status": "Failed",
  "error": {
    "code": "ResourceDeploymentFailure",
    "message": "The resource operation completed with terminal provisioning state 'Failed'.",
    "details": [
      {
        "code": "DeploymentFailed",
        "message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.",
        "details": [
          {
            "code": "Conflict",
            "message": "{\r\n  \"status\": \"Failed\",\r\n  \"error\": {\r\n    \"code\": \"ResourceDeploymentFailure\",\r\n    \"message\": \"The resource operation completed with terminal provisioning state 'Failed'.\",\r\n    \"details\": [\r\n      {\r\n        \"code\": \"NotFound\",\r\n        \"message\": \"Message: {\\\"code\\\":\\\"NotFound\\\",\\\"message\\\":\\\"Message: {\\\\\\\"Errors\\\\\\\":[\\\\\\\"Owner resource does not exist\\\\\\\"]}\\\\r\\\\nActivityId: 4c994fea-249f-4fe2-bdc9-7f9759ef0d15, Request URI: /apps/46a2c1a8-e060-40ad-9893-6f6573d9463d/services/232ea27a-4028-42ee-b997-4cfea450f978/partitions/8c2e10e9-37d3-471a-9f99-be392fa75342/replicas/132659688051702465s, RequestStats: \\\\r\\\\nRequestStartTime: 2021-05-20T13:11:03.8469017Z, RequestEndTime: 2021-05-20T13:11:03.8469017Z,  Number of regions attempted:1\\\\r\\\\nResponseTime: 2021-05-20T13:11:03.8469017Z, StoreResult: StorePhysicalAddress: rntbd://10.0.0.19:11000/apps/46a2c1a8-e060-40ad-9893-6f6573d9463d/services/232ea27a-4028-42ee-b997-4cfea450f978/partitions/8c2e10e9-37d3-471a-9f99-be392fa75342/replicas/132659688051702465s, LSN: 7, GlobalCommittedLsn: 7, PartitionKeyRangeId: , IsValid: True, StatusCode: 404, SubStatusCode: 1003, RequestCharge: 1, ItemLSN: -1, SessionToken: -1#7, UsingLocalLSN: False, TransportException: null, ResourceType: Collection, OperationType: Read\\\\r\\\\nResponseTime: 2021-05-20T13:11:03.8469017Z, StoreResult: StorePhysicalAddress: rntbd://10.0.0.20:11300/apps/46a2c1a8-e060-40ad-9893-6f6573d9463d/services/232ea27a-4028-42ee-b997-4cfea450f978/partitions/8c2e10e9-37d3-471a-9f99-be392fa75342/replicas/132659688051702467s, LSN: 7, GlobalCommittedLsn: 7, PartitionKeyRangeId: , IsValid: True, StatusCode: 404, SubStatusCode: 1003, RequestCharge: 1, ItemLSN: -1, SessionToken: -1#7, UsingLocalLSN: False, TransportException: null, ResourceType: Collection, OperationType: Read\\\\r\\\\n, SDK: Microsoft.Azure.Documents.Common/2.11.0\\\"}, Request URI: /dbs/dbone/colls/collone/udfs, RequestStats: , SDK: Microsoft.Azure.Documents.Common/2.11.0, Microsoft.Azure.Documents.Common/2.11.0, Microsoft.Azure.Documents.Common/2.11.0, Microsoft.Azure.Documents.Common/2.11.0, Microsoft.Azure.Documents.Common/2.11.0\"\r\n      }\r\n    ]\r\n  }\r\n}"
          }
        ]
      }
    ]
  }
}

Here’s a sample from my biceps:

resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-01-15' = {
  name: accountName
  location: location
  kind: 'GlobalDocumentDB'
  properties: {
    consistencyPolicy: {
      defaultConsistencyLevel: 'Session'
    }
    locations: [
      {
        locationName: location
        failoverPriority: 0
        isZoneRedundant: false
      }
    ]
    databaseAccountOfferType: 'Standard'
    enableAutomaticFailover: false
    enableMultipleWriteLocations: false
    publicNetworkAccess: publicNetworkAccess
  }
}

resource cosmosdb 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2021-01-15' = {
  name: '${databaseAccount.name}/${databaseName}'
  properties: {
    resource: {
      id: databaseName
    }
  }
}

resource containers 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2021-01-15' = {
  name: '${databaseAccount.name}/${databaseName}/${containerName}'
  properties: {
    resource: {
      id: containerName
      partitionKey: {
        paths: [
          '/partitionKey'
        ]
        kind: 'Hash'
      }
    }
    options: {
      throughput: throughput
    }
  }
}

resource userDefinedFunctions 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/userDefinedFunctions@2021-01-15' = {
  name: '${databaseAccount.name}/${databaseName}/${containerName}/${userDefinedFunctionName}'
  properties: {
    resource: {
      id: userDefinedFunctionName
      body: 'function checkTime(ts){var ts_date=new Date(ts); var hour=ts_date.getHours(); return hour == 8;}'
    }
  }
}

When I add the last resource userDefinedFunctions, the following error occurs:

az deployment group create -f main.bicep -g myresgroup

It generates a database and a collection, but without sproc or udfs, and with the error mentioned above. I’m a little concerned that it’s still not possible in biceps.

I also tried a variety of other API versions @api.

UPDATE

I created a json file with bicep and verified that the dependsOn property was generated incorrectly:

"dependsOn": [
                "[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('accountName'))]"
              ]

When I switched to:

"dependsOn": [
                "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers', parameters('accountName'), parameters('databaseName'), parameters('containerName'))]"
              ]

deployment was successful.

Is there a way to influence the production of dependsOn properties?

Asked by gorrch

Solution #1

I’ve attached an example that I created by decompiling the arm template sample into bicep.

https://github.com/markjbrown/azure-quickstart-templates/tree/sql-sp/quickstarts/microsoft.documentdb/cosmosdb-sql-container-sprocs

I haven’t had a chance to finish the PR I’m working on for this revised sample, but it will be published where the ARM template you mentioned is located. However, if you need a working example to unblock you, this is it.

UPDATE: Please accept my apologies for the missing bicep file. I’m not sure what happened there.

Take the ARM template found here and give it to bicep’s decompile function to see an example of how to deploy a UDF using bicep. Here’s an example.

bicep decompile "path/to/azuredeploy.json"

The.bicep file that results can then be deployed.

Answered by Mark Brown

Post is based on https://stackoverflow.com/questions/67621183/deployment-of-userdefinedfunction-together-with-azure-cosmos-db-using-bicep