Repository: Azure/azure-sdk-for-go
Pull request #15628 (2021-09-23 22:37:08)

Add goExtension parameter to build.ps1
So you can generate code using any version of autorest.go, including a local one (e.g. `build.ps1 -goExtension=~/autorest.go ...`).


Patch:
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 4bb9bff4cb..ee56890fa3 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -27,6 +27,9 @@
 # PRLabel: %Storage
 /sdk/storage/            @rickwinter @jhendrixMSFT
 
+# PRLabel: %Cosmos
+/sdk/data/azcosmos/        @ealsur @ausfeldt 
+
 # PRLabel: %EngSys
 /sdk/template/           @benbp @Azure/azure-sdk-eng
 
diff --git a/eng/config.json b/eng/config.json
index 13468a9420..e81f7fec16 100644
--- a/eng/config.json
+++ b/eng/config.json
@@ -4,6 +4,10 @@
             "Name": "azidentity",
             "CoverageGoal": 0.68
         },
+        {
+            "Name": "azcosmos",
+            "CoverageGoal": 0.40
+        },
         {
             "Name": "azcore",
             "CoverageGoal": 0.85
diff --git a/eng/scripts/build.ps1 b/eng/scripts/build.ps1
index d6a04e17b9..d958548232 100644
--- a/eng/scripts/build.ps1
+++ b/eng/scripts/build.ps1
@@ -1,5 +1,17 @@
 #Requires -Version 7.0
-param([string]$filter, [switch]$clean, [switch]$vet, [switch]$generate, [switch]$skipBuild, [switch]$cleanGenerated, [switch]$format, [switch]$tidy, [string]$config = "autorest.md", [string]$outputFolder)
+param(
+    [string]$filter,
+    [switch]$clean,
+    [switch]$vet,
+    [switch]$generate,
+    [switch]$skipBuild,
+    [switch]$cleanGenerated,
+    [switch]$format,
+    [switch]$tidy,
+    [string]$config = "autorest.md",
+    [string]$goExtension = "@autorest/go@4.0.0-preview.27",
+    [string]$outputFolder
+)
 
 . (Join-Path $PSScriptRoot .. common scripts common.ps1)
 
@@ -20,11 +32,10 @@ function Process-Sdk () {
         Write-Host "##[command]Executing autorest.go in " $currentDirectory
         $autorestPath = "./" + $config
 
-        $autorestVersion = "@autorest/go@4.0.0-preview.27"
         if ($outputFolder -eq '') {
             $outputFolder = $currentDirectory
         }
-        autorest --use=$autorestVersion --go --track2 --output-folder=$outputFolder --file-prefix="zz_generated_" --clear-output-folder=false $autorestPath
+        autorest --use=$goExtension --go --track2 --output-folder=$outputFolder --file-prefix="zz_generated_" --clear-output-folder=false $autorestPath
         if ($LASTEXITCODE) {
             Write-Host "##[error]Error running autorest.go"
             exit $LASTEXITCODE
diff --git a/sdk/azidentity/CHANGELOG.md b/sdk/azidentity/CHANGELOG.md
index a5674dde65..b8dd5a3fd7 100644
--- a/sdk/azidentity/CHANGELOG.md
+++ b/sdk/azidentity/CHANGELOG.md
@@ -25,6 +25,7 @@
   certData, err := os.ReadFile("/cert.pem")
   cred, err := NewClientCertificateCredential("tenant", "client-id", certData, nil)
   ```
+* Removed `InteractiveBrowserCredentialOptions.ClientSecret` and `.Port`
 
 ### Features Added
 * Added connection configuration options to `DefaultAzureCredentialOptions`
diff --git a/sdk/azidentity/aad_identity_client.go b/sdk/azidentity/aad_identity_client.go
index 18c8dc3cac..5bb9216edf 100644
--- a/sdk/azidentity/aad_identity_client.go
+++ b/sdk/azidentity/aad_identity_client.go
@@ -384,7 +384,7 @@ func (c *aadIdentityClient) authenticateInteractiveBrowser(ctx context.Context,
 	if err != nil {
 		return nil, err
 	}
-	return c.authenticateAuthCode(ctx, opts.TenantID, opts.ClientID, cfg.authCode, opts.ClientSecret, cfg.codeVerifier, cfg.redirectURI, scopes)
+	return c.authenticateAuthCode(ctx, opts.TenantID, opts.ClientID, cfg.authCode, "", cfg.codeVerifier, cfg.redirectURI, scopes)
 }
 
 // authenticateAuthCode requests an Access Token with the authorization code and returns the token or an error in case of authentication failure.
diff --git a/sdk/azidentity/interactive_browser_credential.go b/sdk/azidentity/interactive_browser_credential.go
index 091772a9dd..c83d8fd407 100644
--- a/sdk/azidentity/interactive_browser_credential.go
+++ b/sdk/azidentity/interactive_browser_credential.go
@@ -19,24 +19,18 @@ import (
 	"github.com/pkg/browser"
 )
 
-// InteractiveBrowserCredentialOptions can be used when providing additional credential information, such as a client secret.
+// InteractiveBrowserCredentialOptions provides optional configuration.
 // Use these options to modify the default pipeline behavior if necessary.
 // All zero-value fields will be initialized with their default values. Please note, that both the TenantID or ClientID fields should
 // changed together if default values are not desired.
 type InteractiveBrowserCredentialOptions struct {
-	// The Azure Active Directory tenant (directory) ID of the service principal.
-	// The default value is "organizations". If this value is changed, then also change ClientID to the corresponding value.
+	// The Azure Active Directory tenant (directory) ID of the application. Defaults to "organizations".
 	TenantID string
-	// The client (application) ID of the service principal.
-	// The default value is the developer sign on ID for the corresponding "organizations" TenantID.
+	// The ID of the application the user will sign in to. When not set, users will sign in to an Azure development application.
 	ClientID string
-	// The client secret that was generated for the App Registration used to authenticate the client. Only applies for web apps.
-	ClientSecret string
-	// The redirect URL used to request the authorization code. Must be the same URL that is configured for the App Registration.
+	// RedirectURL will be supported in a future version but presently doesn't work: https://github.com/Azure/azure-sdk-for-go/issues/15632.
+	// Applications which have "http://localhost" registered as a redirect URL need not set this option.
 	RedirectURL string
-	// The localhost port for the local server that will be used to redirect back.
-	// By default, a random port number will be selected.
-	Port int
 	// The host of the Azure Active Directory authority. The default is AzurePublicCloud.
 	// Leave empty to allow overriding the value from the AZURE_AUTHORITY_HOST environment variable.
 	AuthorityHost AuthorityHost
@@ -125,10 +119,7 @@ func interactiveBrowserLogin(ctx context.Context, authorityHost string, opts *In
 	if err != nil {
 		return nil, err
 	}
-	redirectURL := opts.RedirectURL
-	if redirectURL == "" {
-		redirectURL = rs.Start(state.String(), opts.Port)
-	}
+	redirectURL := rs.Start(state.String())
 	defer rs.Stop()
 	u, err := url.Parse(authorityHost)
 	if err != nil {
diff --git a/sdk/azidentity/interactive_browser_server.go b/sdk/azidentity/interactive_browser_server.go
index b6a7edb5e8..1143dd36e1 100644
--- a/sdk/azidentity/interactive_browser_server.go
+++ b/sdk/azidentity/interactive_browser_server.go
@@ -57,10 +57,8 @@ func newServer() *server {
 
 // Start starts the local HTTP server on a separate go routine.
 // The return value is the full URL plus port number.
-func (s *server) Start(reqState string, port int) string {
-	if port == 0 {
-		port = rand.Intn(600) + 8400
-	}
+func (s *server) Start(reqState string) string {
+	port := rand.Intn(600) + 8400
 	s.s.Addr = fmt.Sprintf(":%d", port)
 	s.s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		defer func() {
diff --git a/sdk/data/azcosmos/CHANGELOG.md b/sdk/data/azcosmos/CHANGELOG.md
new file mode 100644
index 0000000000..991c171d1d
--- /dev/null
+++ b/sdk/data/azcosmos/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Release History
+
+## 0.0.1 (Unreleased)
+
+### Added
+    This is the initial preview release of the `azcosmos` library
\ No newline at end of file
diff --git a/sdk/data/azcosmos/LICENSE b/sdk/data/azcosmos/LICENSE
new file mode 100644
index 0000000000..d1ca00f20a
--- /dev/null
+++ b/sdk/data/azcosmos/LICENSE
@@ -0,0 +1,21 @@
+    MIT License
+
+    Copyright (c) Microsoft Corporation. All rights reserved.
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in all
+    copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+    SOFTWARE
\ No newline at end of file
diff --git a/sdk/data/azcosmos/README.md b/sdk/data/azcosmos/README.md
new file mode 100644
index 0000000000..37d0a7e0fc
--- /dev/null
+++ b/sdk/data/azcosmos/README.md
@@ -0,0 +1,142 @@
+# Microsoft Azure Cosmos DB SDK for Go, Golang
+
+## Introduction
+
+This client library enables client applications to connect to Azure Cosmos via the SQL API. Azure Cosmos is a globally distributed, multi-model database service. 
+
+## Getting Started
+
+### Prerequisites
+
+* Go versions 1.16 or higher
+* An Azure subscription or free Azure Cosmos DB trial account
+
+Note: If you don't have an Azure subscription, create a free account before you begin.
+You can Try Azure Cosmos DB for free without an Azure subscription, free of charge and commitments, or create an Azure Cosmos DB free tier account, with the first 400 RU/s and 5 GB of storage for free. You can also use the Azure Cosmos DB Emulator with a URI of https://localhost:8081. For the key to use with the emulator, see Authenticating requests.
+
+### Create an Azure Cosmos account
+
+You can create an Azure Cosmos account using:
+
+* [Azure Portal](https://portal.azure.com).
+* [Azure CLI](https://docs.microsoft.com/cli/azure).
+* [Azure ARM](https://docs.microsoft.com/azure/cosmos-db/quick-create-template).
+
+#### Install the package
+
+* Install the Azure Cosmos DB SDK for Go with `go get`:
+
+  ```bash
+  go get -u github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos
+  ```
+  
+#### Authenticate the client
+
+In order to interact with the Azure CosmosDB service you'll need to create an instance of the Cosmos Client class. To make this possible you will need an URL and key of the Azure CosmosDB service.
+
+## Examples
+
+The following section provides several code snippets covering some of the most common CosmosDB SQL API tasks, including:
+* [Create Cosmos Client](#create-cosmos-client "Create Cosmos Client")
+* [Create Database](#create-database "Create Database")
+* [Create Container](#create-container "Create Container")
+* [CRUD operation on Items](#crud-operation-on-items "CRUD operation on Items")
+
+### Create Cosmos Client
+
+```go
+const (
+    CosmosDbEndpoint = "someEndpoint"
+    CosmoDbKey = "someKey"
+)
+
+cred, _ := NewSharedKeyCredential(CosmosDbEndpoint)
+client, err := NewCosmosClient(CosmoDbKey, cred, &CosmosClientOptions{})
+handle(err)
+```
+
+### Create Database
+
+Using the client created in previous example, you can create a database like this:
+
+```go
+database := CosmosDatabaseProperties{Id: dbName}
+response, err := client.CreateDatabase(context, database, nil, nil)
+handle(err)
+```
+
+### Create Container
+
+Using the above created database for creating a container, like this:
+
+```go
+properties := CosmosContainerProperties{
+    Id: "aContainer",
+    PartitionKeyDefinition: PartitionKeyDefinition{
+        Paths: []string{"/id"},
+    },
+}
+
+throughput := NewManualThroughputProperties(400)
+response, err := database.CreateContainer(context, properties, throughput, nil)
+handle(err)
+container := resp.ContainerProperties.Container
+```
+
+### CRUD operation on Items
+
+```go
+item := map[string]string{
+    "id":    "1",
+    "value": "2",
+}
+
+// Create partition key
+container := client.GetCosmosContainer(dbName, containerName)
+pk, err := NewPartitionKey("1")
+handle(err)
+
+// Create an item
+itemResponse, err := container.CreateItem(context, pk, item, nil)
+handle(err)
+
+itemResponse, err = container.ReadItem(context, pk, "1", nil)
+handle(err)
+
+itemResponse, err = container.ReplaceItem(context, pk, "1", item, nil)
+handle(err)
+
+itemResponse, err = container.DeleteItem(context, pk, "1", nil)
+handle(err)
+```
+
+## Next steps
+
+- [Resource Model of Azure Cosmos DB Service](https://docs.microsoft.com/azure/cosmos-db/sql-api-resources)
+- [Cosmos DB Resource URI](https://docs.microsoft.com/rest/api/documentdb/documentdb-resource-uri-syntax-for-rest)
+- [Partitioning](https://docs.microsoft.com/azure/cosmos-db/partition-data)
+- [Using emulator](https://github.com/Azure/azure-documentdb-dotnet/blob/master/docs/documentdb-nosql-local-emulator.md)
+
+
+## License
+
+This project is licensed under MIT.
+
+## Provide Feedback
+
+If you encounter bugs or have suggestions, please
+[open an issue](https://github.com/Azure/azure-sdk-for-go/issues) and assign the `Azure.data.azcosmos` label.
+
+## Contributing
+
+This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License
+Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For
+details, visit https://cla.microsoft.com.
+
+When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate
+the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to
+do this once across all repos using our CLA.
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
+contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional 
\ No newline at end of file
diff --git a/sdk/data/azcosmos/async_cache.go b/sdk/data/azcosmos/async_cache.go
new file mode 100644
index 0000000000..3fdb540cb3
--- /dev/null
+++ b/sdk/data/azcosmos/async_cache.go
@@ -0,0 +1,161 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"reflect"
+	"sync"
+)
+
+type invalidCacheValue struct{}
+
+func (i invalidCacheValue) Error() string { return "Invalid cache value" }
+
+type asyncCache struct {
+	values sync.Map
+}
+
+type cacheValue struct {
+	value         interface{}
+	obsoleteValue interface{}
+	complete      bool
+	fn            cacheValueTask
+	ch            <-chan *cacheTaskResult
+	err           error
+}
+
+type cacheValueTask func() *cacheTaskResult
+type cacheTaskResult struct {
+	value interface{}
+	err   error
+}
+
+func newAsyncCache() *asyncCache {
+	return &asyncCache{}
+}
+
+func (ac *asyncCache) setValue(key interface{}, value interface{}) {
+	ac.values.Store(key, cacheValue{value: value})
+}
+
+func (ac *asyncCache) set(key interface{}, singleValueInit cacheValueTask, ctx context.Context) error {
+	ch := ac.execCacheValueTask(singleValueInit)
+	cachedValue := cacheValue{complete: false, fn: singleValueInit, ch: ch}
+	ac.values.Store(key, cachedValue)
+	_, err := ac.awaitCacheValue(key, ctx)
+
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (ac *asyncCache) getValue(key interface{}) (interface{}, bool) {
+	var cachedValue cacheValue
+	value, ok := ac.values.Load(key)
+
+	if !ok {
+		return nil, false
+	}
+
+	cachedValue, ok = value.(cacheValue)
+
+	if ok {
+		return cachedValue.value, ok
+	}
+
+	return nil, false
+}
+
+func (ac *asyncCache) getAsync(key interface{}, obsoleteValue interface{}, singleValueInit cacheValueTask) error {
+	var cachedValue cacheValue
+	value, valueExists := ac.values.Load(key)
+
+	if !valueExists {
+		return nil
+	}
+
+	cachedValue, converted := value.(cacheValue)
+
+	if !converted {
+		return invalidCacheValue{}
+	}
+
+	if cachedValue.complete {
+		ch := ac.execCacheValueTask(singleValueInit)
+		cachedValue.obsoleteValue = obsoleteValue
+		cachedValue.complete = false
+		cachedValue.fn = singleValueInit
+		cachedValue.ch = ch
+		ac.values.Store(key, cachedValue)
+	} else {
+		cachedValue.fn = singleValueInit
+		cachedValue.obsoleteValue = obsoleteValue
+		ac.values.Store(key, cachedValue)
+	}
+
+	return nil
+}
+
+func (ac *asyncCache) remove(key interface{}) {
+	ac.values.Delete(key)
+}
+
+func (ac *asyncCache) clear() {
+	ac.values.Range(func(key interface{}, value interface{}) bool {
+		ac.values.Delete(key)
+		return true
+	})
+
+}
+
+func (ac *asyncCache) execCacheValueTask(t cacheValueTask) <-chan *cacheTaskResult {
+	ch := make(chan *cacheTaskResult)
+
+	go func() {
+		defer close(ch)
+		ch <- t()
+	}()
+	return ch
+}
+
+func (ac *asyncCache) awaitCacheValue(key interface{}, ctx context.Context) (interface{}, error) {
+	value, exists := ac.values.Load(key)
+
+	if exists {
+		cachedValue, converted := value.(cacheValue)
+
+		if !converted {
+			return nil, invalidCacheValue{}
+		}
+
+		select {
+		case <-ctx.Done():
+			return nil, ctx.Err()
+		case result := <-cachedValue.ch:
+			if result == nil {
+				return cachedValue.value, cachedValue.err
+			}
+
+			if !reflect.DeepEqual(cachedValue.obsoleteValue, result.value) {
+				cachedValue.value = result.value
+				cachedValue.err = result.err
+				cachedValue.complete = true
+				ac.values.Store(key, cachedValue)
+			} else {
+				newch := ac.execCacheValueTask(cachedValue.fn)
+				cachedValue.ch = newch
+				ac.values.Store(key, cachedValue)
+
+				return ac.awaitCacheValue(key, ctx)
+			}
+		}
+
+		return cachedValue.value, cachedValue.err
+	}
+
+	return nil, nil
+}
diff --git a/sdk/data/azcosmos/ci.yml b/sdk/data/azcosmos/ci.yml
new file mode 100644
index 0000000000..aaff61fac2
--- /dev/null
+++ b/sdk/data/azcosmos/ci.yml
@@ -0,0 +1,27 @@
+# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file.
+trigger:
+  branches:
+    include:
+      - main
+      - hotfix/*
+      - release/*
+  paths:
+    include:
+    - sdk/data/azcosmos/
+
+pr:
+  branches:
+    include:
+      - main
+      - feature/*
+      - hotfix/*
+      - release/*
+  paths:
+    include:
+    - sdk/data/azcosmos/
+
+stages:
+- template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml
+  parameters:
+    ServiceDirectory: 'data/azcosmos'
+    RunTests: true
\ No newline at end of file
diff --git a/sdk/data/azcosmos/composite_index_order.go b/sdk/data/azcosmos/composite_index_order.go
new file mode 100644
index 0000000000..1e34372565
--- /dev/null
+++ b/sdk/data/azcosmos/composite_index_order.go
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// These are the ordering values available for composite indexes in the Azure Cosmos DB database service.
+// For more information see https://docs.microsoft.com/azure/cosmos-db/index-policy
+type CompositeIndexOrder string
+
+const (
+	// Ascending sort order for composite paths.
+	CompositeIndexAscending CompositeIndexOrder = "ascending"
+	// Descending sort order for composite paths.
+	CompositeIndexDescending CompositeIndexOrder = "descending"
+)
+
+// Returns a list of available consistency levels
+func CompositeIndexOrderValues() []CompositeIndexOrder {
+	return []CompositeIndexOrder{CompositeIndexAscending, CompositeIndexDescending}
+}
+
+func (c CompositeIndexOrder) ToPtr() *CompositeIndexOrder {
+	return &c
+}
diff --git a/sdk/data/azcosmos/conflict_resolution_mode.go b/sdk/data/azcosmos/conflict_resolution_mode.go
new file mode 100644
index 0000000000..f88d047c85
--- /dev/null
+++ b/sdk/data/azcosmos/conflict_resolution_mode.go
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// ConflictResolutionMode defines the conflict resolution mode in the Azure Cosmos DB service.
+type ConflictResolutionMode string
+
+const (
+	// Conflict resolution that uses the highest value of the conflicting documents property values.
+	ConflictResolutionModeLastWriteWins ConflictResolutionMode = "LastWriterWins"
+	// Custom conflict resolution mode that requires the definition of a stored procedure.
+	ConflictResolutionModeCustom ConflictResolutionMode = "Custom"
+)
+
+// Returns a list of available consistency levels
+func ConflictResolutionModeValues() []ConflictResolutionMode {
+	return []ConflictResolutionMode{ConflictResolutionModeLastWriteWins, ConflictResolutionModeCustom}
+}
+
+func (c ConflictResolutionMode) ToPtr() *ConflictResolutionMode {
+	return &c
+}
diff --git a/sdk/data/azcosmos/conflict_resolution_policy.go b/sdk/data/azcosmos/conflict_resolution_policy.go
new file mode 100644
index 0000000000..276f1e2b06
--- /dev/null
+++ b/sdk/data/azcosmos/conflict_resolution_policy.go
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// ConflictResolutionPolicy represents a conflict resolution policy for a container.
+// For more information see https://docs.microsoft.com/azure/cosmos-db/unique-keys
+type ConflictResolutionPolicy struct {
+	// Conflict resolution mode. By default, the conflict resolution mode is LastWriteWins.
+	Mode ConflictResolutionMode `json:"mode"`
+	// The path which is present in each item in the container to be used on LastWriteWins conflict resolution.
+	// It must be an integer value.
+	ResolutionPath string `json:"conflictResolutionPath,omitempty"`
+	// The stored procedure path on Custom conflict.
+	// The path should be the full path to the procedure
+	ResolutionProcedure string `json:"conflictResolutionProcedure,omitempty"`
+}
diff --git a/sdk/data/azcosmos/consistency_level.go b/sdk/data/azcosmos/consistency_level.go
new file mode 100644
index 0000000000..5655842677
--- /dev/null
+++ b/sdk/data/azcosmos/consistency_level.go
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// Consistency levels supported by the Azure Cosmos DB service.
+type ConsistencyLevel string
+
+const (
+	ConsistencyLevelStrong           ConsistencyLevel = "Strong"
+	ConsistencyLevelBoundedStaleness ConsistencyLevel = "BoundedStaleness"
+	ConsistencyLevelSession          ConsistencyLevel = "Session"
+	ConsistencyLevelEventual         ConsistencyLevel = "Eventual"
+	ConsistencyLevelConsistentPrefix ConsistencyLevel = "ConsistentPrefix"
+)
+
+// Returns a list of available consistency levels
+func ConsistencyLevelValues() []ConsistencyLevel {
+	return []ConsistencyLevel{ConsistencyLevelStrong, ConsistencyLevelBoundedStaleness, ConsistencyLevelSession, ConsistencyLevelEventual, ConsistencyLevelConsistentPrefix}
+}
+
+func (c ConsistencyLevel) ToPtr() *ConsistencyLevel {
+	return &c
+}
diff --git a/sdk/data/azcosmos/cosmos_client.go b/sdk/data/azcosmos/cosmos_client.go
new file mode 100644
index 0000000000..c035f623ac
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_client.go
@@ -0,0 +1,104 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"errors"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
+)
+
+// A CosmosClient is used to interact with the Azure Cosmos DB database service.
+type CosmosClient struct {
+	// Endpoint used to create the client.
+	Endpoint   string
+	connection *cosmosClientConnection
+	cred       *SharedKeyCredential
+	options    *CosmosClientOptions
+}
+
+// NewCosmosClient creates a new instance of CosmosClient with the specified values. It uses the default pipeline configuration.
+// endpoint - The cosmos service endpoint to use.
+// cred - The credential used to authenticate with the cosmos service.
+// options - Optional CosmosClient options.  Pass nil to accept default values.
+func NewCosmosClient(endpoint string, cred azcore.Credential, options *CosmosClientOptions) (*CosmosClient, error) {
+	if options == nil {
+		options = &CosmosClientOptions{}
+	}
+
+	connection := newCosmosClientConnection(endpoint, cred, options)
+
+	c, _ := cred.(*SharedKeyCredential)
+
+	return &CosmosClient{Endpoint: endpoint, connection: connection, cred: c, options: options}, nil
+}
+
+// GetCosmosDatabase returns a CosmosDatabase object.
+// id - The id of the database.
+func (c *CosmosClient) GetCosmosDatabase(id string) (*CosmosDatabase, error) {
+	if id == "" {
+		return nil, errors.New("id is required")
+	}
+
+	return newCosmosDatabase(id, c), nil
+}
+
+// GetCosmosContainer returns a CosmosContainer object.
+// databaseId - The id of the database.
+// containerId - The id of the container.
+func (c *CosmosClient) GetCosmosContainer(databaseId string, containerId string) (*CosmosContainer, error) {
+	if databaseId == "" {
+		return nil, errors.New("databaseId is required")
+	}
+
+	if containerId == "" {
+		return nil, errors.New("containerId is required")
+	}
+
+	return newCosmosDatabase(databaseId, c).GetContainer(containerId)
+}
+
+// CreateDatabase creates a new database.
+// ctx - The context for the request.
+// databaseProperties - The definition of the database
+// throughputProperties - Optional throughput configuration of the database
+// requestOptions - Optional parameters for the request.
+func (c *CosmosClient) CreateDatabase(
+	ctx context.Context,
+	databaseProperties CosmosDatabaseProperties,
+	throughputProperties *ThroughputProperties,
+	requestOptions *CosmosDatabaseRequestOptions) (CosmosDatabaseResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &CosmosDatabaseRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: "",
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDatabase, "", true)
+	if err != nil {
+		return CosmosDatabaseResponse{}, err
+	}
+
+	database, err := c.GetCosmosDatabase(databaseProperties.Id)
+	if err != nil {
+		return CosmosDatabaseResponse{}, err
+	}
+
+	azResponse, err := c.connection.sendPostRequest(
+		path,
+		ctx,
+		databaseProperties,
+		operationContext,
+		requestOptions,
+		throughputProperties.addHeadersToRequest)
+	if err != nil {
+		return CosmosDatabaseResponse{}, err
+	}
+
+	return newCosmosDatabaseResponse(azResponse, database)
+}
diff --git a/sdk/data/azcosmos/cosmos_client_connection.go b/sdk/data/azcosmos/cosmos_client_connection.go
new file mode 100644
index 0000000000..65d86a605f
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_client_connection.go
@@ -0,0 +1,187 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"net/http"
+	"time"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+)
+
+// cosmosClientConnection maintains a Pipeline for the client.
+// The Pipeline is build based on the CosmosClientOptions.
+type cosmosClientConnection struct {
+	endpoint string
+	Pipeline azruntime.Pipeline
+}
+
+// newConnection creates an instance of the connection type with the specified endpoint.
+// Pass nil to accept the default options; this is the same as passing a zero-value options.
+func newCosmosClientConnection(endpoint string, cred azcore.Credential, options *CosmosClientOptions) *cosmosClientConnection {
+	policies := []policy.Policy{
+		azruntime.NewTelemetryPolicy("azcosmos", serviceLibVersion, &options.Telemetry),
+	}
+	policies = append(policies, options.PerCallPolicies...)
+	policies = append(policies, azruntime.NewRetryPolicy(&options.Retry))
+	policies = append(policies, options.PerRetryPolicies...)
+	policies = append(policies, options.getSDKInternalPolicies()...)
+	policies = append(policies, cred.NewAuthenticationPolicy(azruntime.AuthenticationOptions{}))
+	policies = append(policies, azruntime.NewLogPolicy(&options.Logging))
+	return &cosmosClientConnection{endpoint: endpoint, Pipeline: azruntime.NewPipeline(options.HTTPClient, policies...)}
+}
+
+func (c *cosmosClientConnection) sendPostRequest(
+	path string,
+	ctx context.Context,
+	content interface{},
+	operationContext cosmosOperationContext,
+	requestOptions cosmosRequestOptions,
+	requestEnricher func(*policy.Request)) (*http.Response, error) {
+	req, err := c.createRequest(path, ctx, http.MethodPost, operationContext, requestOptions, requestEnricher)
+	if err != nil {
+		return nil, err
+	}
+
+	err = azruntime.MarshalAsJSON(req, content)
+	if err != nil {
+		return nil, err
+	}
+
+	return c.executeAndEnsureSuccessResponse(req)
+}
+
+func (c *cosmosClientConnection) sendQueryRequest(
+	path string,
+	ctx context.Context,
+	query string,
+	operationContext cosmosOperationContext,
+	requestOptions cosmosRequestOptions,
+	requestEnricher func(*policy.Request)) (*http.Response, error) {
+	req, err := c.createRequest(path, ctx, http.MethodPost, operationContext, requestOptions, requestEnricher)
+	if err != nil {
+		return nil, err
+	}
+
+	type queryBody struct {
+		Query string `json:"query"`
+	}
+
+	err = azruntime.MarshalAsJSON(req, queryBody{
+		Query: query,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	req.Raw().Header.Add(cosmosHeaderQuery, "True")
+	// Override content type for query
+	req.Raw().Header.Set(headerContentType, cosmosHeaderValuesQuery)
+
+	return c.executeAndEnsureSuccessResponse(req)
+}
+
+func (c *cosmosClientConnection) sendPutRequest(
+	path string,
+	ctx context.Context,
+	content interface{},
+	operationContext cosmosOperationContext,
+	requestOptions cosmosRequestOptions,
+	requestEnricher func(*policy.Request)) (*http.Response, error) {
+	req, err := c.createRequest(path, ctx, http.MethodPut, operationContext, requestOptions, requestEnricher)
+	if err != nil {
+		return nil, err
+	}
+
+	err = azruntime.MarshalAsJSON(req, content)
+	if err != nil {
+		return nil, err
+	}
+
+	return c.executeAndEnsureSuccessResponse(req)
+}
+
+func (c *cosmosClientConnection) sendGetRequest(
+	path string,
+	ctx context.Context,
+	operationContext cosmosOperationContext,
+	requestOptions cosmosRequestOptions,
+	requestEnricher func(*policy.Request)) (*http.Response, error) {
+	req, err := c.createRequest(path, ctx, http.MethodGet, operationContext, requestOptions, requestEnricher)
+	if err != nil {
+		return nil, err
+	}
+
+	return c.executeAndEnsureSuccessResponse(req)
+}
+
+func (c *cosmosClientConnection) sendDeleteRequest(
+	path string,
+	ctx context.Context,
+	operationContext cosmosOperationContext,
+	requestOptions cosmosRequestOptions,
+	requestEnricher func(*policy.Request)) (*http.Response, error) {
+	req, err := c.createRequest(path, ctx, http.MethodDelete, operationContext, requestOptions, requestEnricher)
+	if err != nil {
+		return nil, err
+	}
+
+	return c.executeAndEnsureSuccessResponse(req)
+}
+
+func (c *cosmosClientConnection) createRequest(
+	path string,
+	ctx context.Context,
+	method string,
+	operationContext cosmosOperationContext,
+	requestOptions cosmosRequestOptions,
+	requestEnricher func(*policy.Request)) (*policy.Request, error) {
+
+	// todo: endpoint will be set originally by globalendpointmanager
+	finalURL := c.endpoint
+
+	if path != "" {
+		finalURL = azruntime.JoinPaths(c.endpoint, path)
+	}
+
+	req, err := azruntime.NewRequest(ctx, method, finalURL)
+	if err != nil {
+		return nil, err
+	}
+
+	headers := requestOptions.toHeaders()
+	if headers != nil {
+		for k, v := range *headers {
+			req.Raw().Header.Set(k, v)
+		}
+	}
+
+	req.Raw().Header.Set(headerXmsDate, time.Now().UTC().Format(http.TimeFormat))
+	req.Raw().Header.Set(headerXmsVersion, "2020-11-05")
+
+	req.SetOperationValue(operationContext)
+
+	if requestEnricher != nil {
+		requestEnricher(req)
+	}
+
+	return req, nil
+}
+
+func (c *cosmosClientConnection) executeAndEnsureSuccessResponse(request *policy.Request) (*http.Response, error) {
+	response, err := c.Pipeline.Do(request)
+	if err != nil {
+		return nil, err
+	}
+
+	successResponse := (response.StatusCode >= 200 && response.StatusCode < 300) || response.StatusCode == 304
+	if successResponse {
+		return response, nil
+	}
+
+	return nil, newCosmosError(response)
+}
diff --git a/sdk/data/azcosmos/cosmos_client_options.go b/sdk/data/azcosmos/cosmos_client_options.go
new file mode 100644
index 0000000000..1177d5c9f4
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_client_options.go
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"time"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+)
+
+// CosmosClientOptions defines the options for the Cosmos client.
+type CosmosClientOptions struct {
+	// HTTPClient sets the transport for making HTTP requests.
+	HTTPClient policy.Transporter
+	// Retry configures the built-in retry policy behavior.
+	Retry policy.RetryOptions
+	// Telemetry configures the built-in telemetry policy behavior.
+	Telemetry policy.TelemetryOptions
+	// Logging configures the built-in logging policy behavior.
+	Logging policy.LogOptions
+	// PerCallPolicies contains custom policies to inject into the pipeline.
+	// Each policy is executed once per request.
+	PerCallPolicies []policy.Policy
+	// PerRetryPolicies contains custom policies to inject into the pipeline.
+	// Each policy is executed once per request, and for each retry request.
+	PerRetryPolicies []policy.Policy
+	// ApplicationPreferredRegions defines list of preferred regions for the client to connect to.
+	ApplicationPreferredRegions *[]string
+	// ConsistencyLevel can be used to weaken the database account consistency level for read operations. If this is not set the database account consistency level will be used for all requests.
+	ConsistencyLevel ConsistencyLevel
+	// When EnableContentResponseOnWrite is false will cause the response to have a null resource. This reduces networking and CPU load by not sending the resource back over the network and serializing it on the client.
+	// The default is false.
+	EnableContentResponseOnWrite bool
+	// LimitToEndpoint limits the operations to the provided endpoint on the CosmosClient. See https://docs.microsoft.com/azure/cosmos-db/troubleshoot-sdk-availability
+	LimitToEndpoint bool
+	// RateLimitedRetry defines the retry configuration for rate limited requests.
+	// By default, the SDK will do 9 retries.
+	RateLimitedRetry *CosmosClientOptionsRateLimitedRetry
+}
+
+type CosmosClientOptionsRateLimitedRetry struct {
+	// MaxRetryAttempts specifies the number of retries to perform on rate limited requests.
+	MaxRetryAttempts int
+	// MaxRetryWaitTime specifies the maximum time to wait for retries.
+	MaxRetryWaitTime time.Duration
+}
+
+// getSDKInternalPolicies builds a list of internal retry policies for the cosmos service.
+// This includes throttling and failover policies.
+func (o *CosmosClientOptions) getSDKInternalPolicies() []policy.Policy {
+	return []policy.Policy{
+		newResourceThrottleRetryPolicy(o),
+		// TODO: Add more policies here.
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_container.go b/sdk/data/azcosmos/cosmos_container.go
new file mode 100644
index 0000000000..a9a6572c63
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_container.go
@@ -0,0 +1,432 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"errors"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+)
+
+// A CosmosContainer lets you perform read, update, change throughput, and delete container operations.
+// It also lets you perform read, update, change throughput, and delete item operations.
+type CosmosContainer struct {
+	// The Id of the Cosmos container
+	Id string
+	// The database that contains the container
+	Database *CosmosDatabase
+	// The resource link
+	link string
+}
+
+func newCosmosContainer(id string, database *CosmosDatabase) *CosmosContainer {
+	return &CosmosContainer{
+		Id:       id,
+		Database: database,
+		link:     createLink(database.link, pathSegmentCollection, id)}
+}
+
+// Read obtains the information for a Cosmos container.
+// ctx - The context for the request.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) Read(
+	ctx context.Context,
+	requestOptions *CosmosContainerRequestOptions) (CosmosContainerResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &CosmosContainerRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeCollection,
+		resourceAddress: c.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeCollection, c.link, false)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendGetRequest(
+		path,
+		ctx,
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	return newCosmosContainerResponse(azResponse, c)
+}
+
+// Replace a Cosmos container.
+// ctx - The context for the request.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) Replace(
+	ctx context.Context,
+	containerProperties CosmosContainerProperties,
+	requestOptions *CosmosContainerRequestOptions) (CosmosContainerResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &CosmosContainerRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeCollection,
+		resourceAddress: c.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeCollection, c.link, false)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendPutRequest(
+		path,
+		ctx,
+		containerProperties,
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	return newCosmosContainerResponse(azResponse, c)
+}
+
+// Delete a Cosmos container.
+// ctx - The context for the request.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) Delete(
+	ctx context.Context,
+	requestOptions *CosmosContainerRequestOptions) (CosmosContainerResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &CosmosContainerRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeCollection,
+		resourceAddress: c.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeCollection, c.link, false)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendDeleteRequest(
+		path,
+		ctx,
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	return newCosmosContainerResponse(azResponse, c)
+}
+
+// ReadThroughput obtains the provisioned throughput information for the container.
+// ctx - The context for the request.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) ReadThroughput(
+	ctx context.Context,
+	requestOptions *ThroughputRequestOptions) (ThroughputResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &ThroughputRequestOptions{}
+	}
+
+	rid, err := c.getRID(ctx)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	offers := &cosmosOffers{connection: c.Database.client.connection}
+	return offers.ReadThroughputIfExists(ctx, rid, requestOptions)
+}
+
+// ReplaceThroughput updates the provisioned throughput for the container.
+// ctx - The context for the request.
+// throughputProperties - The throughput configuration of the container.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) ReplaceThroughput(
+	ctx context.Context,
+	throughputProperties ThroughputProperties,
+	requestOptions *ThroughputRequestOptions) (ThroughputResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &ThroughputRequestOptions{}
+	}
+
+	rid, err := c.getRID(ctx)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	offers := &cosmosOffers{connection: c.Database.client.connection}
+	return offers.ReadThroughputIfExists(ctx, rid, requestOptions)
+}
+
+// Creates an item in a Cosmos container.
+// ctx - The context for the request.
+// partitionKey - The partition key for the item.
+// item - The item to create.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) CreateItem(
+	ctx context.Context,
+	partitionKey *PartitionKey,
+	item interface{},
+	requestOptions *CosmosItemRequestOptions) (CosmosItemResponse, error) {
+
+	addHeader, err := c.buildRequestEnricher(partitionKey, requestOptions, true)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	if requestOptions == nil {
+		requestOptions = &CosmosItemRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDocument,
+		resourceAddress: c.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDocument, c.link, true)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendPostRequest(
+		path,
+		ctx,
+		item,
+		operationContext,
+		requestOptions,
+		addHeader)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	return newCosmosItemResponse(azResponse)
+}
+
+// Upserts (create or replace) an item in a Cosmos container.
+// ctx - The context for the request.
+// partitionKey - The partition key for the item.
+// item - The item to upsert.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) UpsertItem(
+	ctx context.Context,
+	partitionKey *PartitionKey,
+	item interface{},
+	requestOptions *CosmosItemRequestOptions) (CosmosItemResponse, error) {
+
+	addHeaderInternal, err := c.buildRequestEnricher(partitionKey, requestOptions, true)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	addHeader := func(r *policy.Request) {
+		addHeaderInternal(r)
+		r.Raw().Header.Add(cosmosHeaderIsUpsert, "true")
+	}
+
+	if requestOptions == nil {
+		requestOptions = &CosmosItemRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDocument,
+		resourceAddress: c.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDocument, c.link, true)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendPostRequest(
+		path,
+		ctx,
+		item,
+		operationContext,
+		requestOptions,
+		addHeader)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	return newCosmosItemResponse(azResponse)
+}
+
+// Replaces an item in a Cosmos container.
+// ctx - The context for the request.
+// partitionKey - The partition key of the item to replace.
+// itemId - The id of the item to replace.
+// item - The content to be used to replace.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) ReplaceItem(
+	ctx context.Context,
+	partitionKey *PartitionKey,
+	itemId string,
+	item interface{},
+	requestOptions *CosmosItemRequestOptions) (CosmosItemResponse, error) {
+
+	addHeader, err := c.buildRequestEnricher(partitionKey, requestOptions, true)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	if requestOptions == nil {
+		requestOptions = &CosmosItemRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDocument,
+		resourceAddress: createLink(c.link, pathSegmentDocument, itemId),
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDocument, operationContext.resourceAddress, false)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendPutRequest(
+		path,
+		ctx,
+		item,
+		operationContext,
+		requestOptions,
+		addHeader)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	return newCosmosItemResponse(azResponse)
+}
+
+// Reads an item in a Cosmos container.
+// ctx - The context for the request.
+// partitionKey - The partition key for the item.
+// itemId - The id of the item to read.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) ReadItem(
+	ctx context.Context,
+	partitionKey *PartitionKey,
+	itemId string,
+	requestOptions *CosmosItemRequestOptions) (CosmosItemResponse, error) {
+
+	addHeader, err := c.buildRequestEnricher(partitionKey, requestOptions, false)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	if requestOptions == nil {
+		requestOptions = &CosmosItemRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDocument,
+		resourceAddress: createLink(c.link, pathSegmentDocument, itemId),
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDocument, operationContext.resourceAddress, false)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendGetRequest(
+		path,
+		ctx,
+		operationContext,
+		requestOptions,
+		addHeader)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	return newCosmosItemResponse(azResponse)
+}
+
+// Deletes an item in a Cosmos container.
+// ctx - The context for the request.
+// partitionKey - The partition key for the item.
+// itemId - The id of the item to delete.
+// requestOptions - Optional parameters for the request.
+func (c *CosmosContainer) DeleteItem(
+	ctx context.Context,
+	partitionKey *PartitionKey,
+	itemId string,
+	requestOptions *CosmosItemRequestOptions) (CosmosItemResponse, error) {
+
+	addHeader, err := c.buildRequestEnricher(partitionKey, requestOptions, true)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	if requestOptions == nil {
+		requestOptions = &CosmosItemRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDocument,
+		resourceAddress: createLink(c.link, pathSegmentDocument, itemId),
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDocument, operationContext.resourceAddress, false)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	azResponse, err := c.Database.client.connection.sendDeleteRequest(
+		path,
+		ctx,
+		operationContext,
+		requestOptions,
+		addHeader)
+	if err != nil {
+		return CosmosItemResponse{}, err
+	}
+
+	return newCosmosItemResponse(azResponse)
+}
+
+func (c *CosmosContainer) buildRequestEnricher(
+	partitionKey *PartitionKey,
+	requestOptions *CosmosItemRequestOptions,
+	writeOperation bool) (func(r *policy.Request), error) {
+	if partitionKey == nil {
+		return nil, errors.New("partitionKey is required")
+	}
+
+	pk, err := partitionKey.toJsonString()
+	if err != nil {
+		return nil, err
+	}
+
+	var enableContentResponseOnWrite bool
+	if requestOptions == nil {
+		enableContentResponseOnWrite = c.Database.client.options.EnableContentResponseOnWrite
+	} else {
+		enableContentResponseOnWrite = requestOptions.EnableContentResponseOnWrite
+	}
+
+	return func(r *policy.Request) {
+		r.Raw().Header.Add(cosmosHeaderPartitionKey, pk)
+		if writeOperation && !enableContentResponseOnWrite {
+			r.Raw().Header.Add(cosmosHeaderPrefer, cosmosHeaderValuesPreferMinimal)
+		}
+	}, nil
+}
+
+func (c *CosmosContainer) getRID(ctx context.Context) (string, error) {
+	containerResponse, err := c.Read(ctx, nil)
+	if err != nil {
+		return "", err
+	}
+
+	return containerResponse.ContainerProperties.ResourceId, nil
+}
diff --git a/sdk/data/azcosmos/cosmos_container_properties.go b/sdk/data/azcosmos/cosmos_container_properties.go
new file mode 100644
index 0000000000..0be31741ab
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_container_properties.go
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// CosmosContainerProperties represents the properties of a container.
+type CosmosContainerProperties struct {
+	// Id contains the unique id of the container.
+	Id string `json:"id"`
+	// ETag contains the entity etag of the container.
+	ETag string `json:"_etag,omitempty"`
+	// SelfLink contains the self-link of the container.
+	SelfLink string `json:"_self,omitempty"`
+	// ResourceId contains the resource id of the container.
+	ResourceId string `json:"_rid,omitempty"`
+	// LastModified contains the last modified time of the container.
+	LastModified *UnixTime `json:"_ts,omitempty"`
+	// DefaultTimeToLive contains the default time to live in seconds for items in the container.
+	// For more information see https://docs.microsoft.com/azure/cosmos-db/time-to-live#time-to-live-configurations
+	DefaultTimeToLive *int `json:"defaultTtl,omitempty"`
+	// AnalyticalStoreTimeToLiveInSeconds contains the default time to live in seconds for analytical store in the container.
+	// For more information see https://docs.microsoft.com/azure/cosmos-db/analytical-store-introduction#analytical-ttl
+	AnalyticalStoreTimeToLiveInSeconds *int `json:"analyticalStorageTtl,omitempty"`
+	// PartitionKeyDefinition contains the partition key definition of the container.
+	PartitionKeyDefinition PartitionKeyDefinition `json:"partitionKey,omitempty"`
+	// IndexingPolicy contains the indexing definition of the container.
+	IndexingPolicy *IndexingPolicy `json:"indexingPolicy,omitempty"`
+	// UniqueKeyPolicy contains the unique key policy of the container.
+	UniqueKeyPolicy *UniqueKeyPolicy `json:"uniqueKeyPolicy,omitempty"`
+	// ConflictResolutionPolicy contains the conflict resolution policy of the container.
+	ConflictResolutionPolicy *ConflictResolutionPolicy `json:"conflictResolutionPolicy,omitempty"`
+	// Container represented by these properties
+	Container *CosmosContainer `json:"-"`
+}
diff --git a/sdk/data/azcosmos/cosmos_container_request_options.go b/sdk/data/azcosmos/cosmos_container_request_options.go
new file mode 100644
index 0000000000..17494c3745
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_container_request_options.go
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// CosmosContainerRequestOptions includes options for operations against a database.
+type CosmosContainerRequestOptions struct {
+	PopulateQuotaInfo bool
+}
+
+func (options *CosmosContainerRequestOptions) toHeaders() *map[string]string {
+	if !options.PopulateQuotaInfo {
+		return nil
+	}
+
+	headers := make(map[string]string)
+	if options.PopulateQuotaInfo {
+		headers[cosmosHeaderPopulateQuotaInfo] = "true"
+	}
+	return &headers
+}
diff --git a/sdk/data/azcosmos/cosmos_container_response.go b/sdk/data/azcosmos/cosmos_container_response.go
new file mode 100644
index 0000000000..d69e727597
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_container_response.go
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"net/http"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+)
+
+// CosmosContainerResponse represents the response from a container request.
+type CosmosContainerResponse struct {
+	// ContainerProperties contains the unmarshalled response body in CosmosContainerProperties format.
+	ContainerProperties *CosmosContainerProperties
+	CosmosResponse
+}
+
+func newCosmosContainerResponse(resp *http.Response, container *CosmosContainer) (CosmosContainerResponse, error) {
+	response := CosmosContainerResponse{}
+	response.RawResponse = resp
+	properties := &CosmosContainerProperties{}
+	err := azruntime.UnmarshalAsJSON(resp, properties)
+	if err != nil {
+		return response, err
+	}
+	response.ContainerProperties = properties
+	response.ContainerProperties.Container = container
+	return response, nil
+}
diff --git a/sdk/data/azcosmos/cosmos_database.go b/sdk/data/azcosmos/cosmos_database.go
new file mode 100644
index 0000000000..06b37f436d
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_database.go
@@ -0,0 +1,194 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"errors"
+)
+
+// A CosmosDatabase lets you perform read, update, change throughput, and delete database operations.
+type CosmosDatabase struct {
+	// The Id of the Cosmos database
+	Id string
+	// The client associated with the Cosmos database
+	client *CosmosClient
+	// The resource link
+	link string
+}
+
+func newCosmosDatabase(id string, client *CosmosClient) *CosmosDatabase {
+	return &CosmosDatabase{
+		Id:     id,
+		client: client,
+		link:   createLink("", pathSegmentDatabase, id)}
+}
+
+// GetContainer returns a CosmosContainer object for the container.
+// id - The id of the container.
+func (db *CosmosDatabase) GetContainer(id string) (*CosmosContainer, error) {
+	if id == "" {
+		return nil, errors.New("id is required")
+	}
+
+	return newCosmosContainer(id, db), nil
+}
+
+// CreateContainer creates a container in the Cosmos database.
+// ctx - The context for the request.
+// containerProperties - The properties for the container.
+// throughputProperties - Optional throughput configuration of the container
+// requestOptions - Optional parameters for the request.
+func (db *CosmosDatabase) CreateContainer(
+	ctx context.Context,
+	containerProperties CosmosContainerProperties,
+	throughputProperties *ThroughputProperties,
+	requestOptions *CosmosContainerRequestOptions) (CosmosContainerResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &CosmosContainerRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeCollection,
+		resourceAddress: db.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeCollection, db.link, true)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	container, err := db.GetContainer(containerProperties.Id)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	azResponse, err := db.client.connection.sendPostRequest(
+		path,
+		ctx,
+		containerProperties,
+		operationContext,
+		requestOptions,
+		throughputProperties.addHeadersToRequest)
+	if err != nil {
+		return CosmosContainerResponse{}, err
+	}
+
+	return newCosmosContainerResponse(azResponse, container)
+}
+
+// Read obtains the information for a Cosmos database.
+// ctx - The context for the request.
+// requestOptions - Optional parameters for the request.
+func (db *CosmosDatabase) Read(
+	ctx context.Context,
+	requestOptions *CosmosDatabaseRequestOptions) (CosmosDatabaseResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &CosmosDatabaseRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: db.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDatabase, db.link, false)
+	if err != nil {
+		return CosmosDatabaseResponse{}, err
+	}
+
+	azResponse, err := db.client.connection.sendGetRequest(
+		path,
+		ctx,
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return CosmosDatabaseResponse{}, err
+	}
+
+	return newCosmosDatabaseResponse(azResponse, db)
+}
+
+// ReadThroughput obtains the provisioned throughput information for the database.
+// ctx - The context for the request.
+// requestOptions - Optional parameters for the request.
+func (db *CosmosDatabase) ReadThroughput(
+	ctx context.Context,
+	requestOptions *ThroughputRequestOptions) (ThroughputResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &ThroughputRequestOptions{}
+	}
+
+	rid, err := db.getRID(ctx)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	offers := &cosmosOffers{connection: db.client.connection}
+	return offers.ReadThroughputIfExists(ctx, rid, requestOptions)
+}
+
+// ReplaceThroughput updates the provisioned throughput for the database.
+// ctx - The context for the request.
+// throughputProperties - The throughput configuration of the database.
+// requestOptions - Optional parameters for the request.
+func (db *CosmosDatabase) ReplaceThroughput(
+	ctx context.Context,
+	throughputProperties ThroughputProperties,
+	requestOptions *ThroughputRequestOptions) (ThroughputResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &ThroughputRequestOptions{}
+	}
+
+	rid, err := db.getRID(ctx)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	offers := &cosmosOffers{connection: db.client.connection}
+	return offers.ReadThroughputIfExists(ctx, rid, requestOptions)
+}
+
+// Delete a Cosmos database.
+// ctx - The context for the request.
+// requestOptions - Optional parameters for the request.
+func (db *CosmosDatabase) Delete(
+	ctx context.Context,
+	requestOptions *CosmosDatabaseRequestOptions) (CosmosDatabaseResponse, error) {
+	if requestOptions == nil {
+		requestOptions = &CosmosDatabaseRequestOptions{}
+	}
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: db.link,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeDatabase, db.link, false)
+	if err != nil {
+		return CosmosDatabaseResponse{}, err
+	}
+
+	azResponse, err := db.client.connection.sendDeleteRequest(
+		path,
+		ctx,
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return CosmosDatabaseResponse{}, err
+	}
+
+	return newCosmosDatabaseResponse(azResponse, db)
+}
+
+func (db *CosmosDatabase) getRID(ctx context.Context) (string, error) {
+	dbResponse, err := db.Read(ctx, nil)
+	if err != nil {
+		return "", err
+	}
+
+	return dbResponse.DatabaseProperties.ResourceId, nil
+}
diff --git a/sdk/data/azcosmos/cosmos_database_properties.go b/sdk/data/azcosmos/cosmos_database_properties.go
new file mode 100644
index 0000000000..e303947b71
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_database_properties.go
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// CosmosDatabaseProperties represents the properties of a database.
+type CosmosDatabaseProperties struct {
+	// Id contains the unique id of the database.
+	Id string `json:"id"`
+	// ETag contains the entity etag of the database
+	ETag string `json:"_etag,omitempty"`
+	// SelfLink contains the self-link of the database
+	SelfLink string `json:"_self,omitempty"`
+	// ResourceId contains the resource id of the database
+	ResourceId string `json:"_rid,omitempty"`
+	// LastModified contains the last modified time of the database
+	LastModified *UnixTime `json:"_ts,omitempty"`
+	// Database represented by these properties
+	Database *CosmosDatabase `json:"-"`
+}
diff --git a/sdk/data/azcosmos/cosmos_database_request_options.go b/sdk/data/azcosmos/cosmos_database_request_options.go
new file mode 100644
index 0000000000..ae9c365643
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_database_request_options.go
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// CosmosDatabaseRequestOptions includes options for operations against a database.
+type CosmosDatabaseRequestOptions struct {
+	IfMatchEtag     string
+	IfNoneMatchEtag string
+}
+
+func (options *CosmosDatabaseRequestOptions) toHeaders() *map[string]string {
+	if options.IfMatchEtag == "" && options.IfNoneMatchEtag == "" {
+		return nil
+	}
+
+	headers := make(map[string]string)
+	if options.IfMatchEtag != "" {
+		headers[headerIfMatch] = options.IfMatchEtag
+	}
+	if options.IfNoneMatchEtag != "" {
+		headers[headerIfNoneMatch] = options.IfNoneMatchEtag
+	}
+	return &headers
+}
diff --git a/sdk/data/azcosmos/cosmos_database_response.go b/sdk/data/azcosmos/cosmos_database_response.go
new file mode 100644
index 0000000000..2ae196956d
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_database_response.go
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"net/http"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+)
+
+// CosmosDatabaseResponse represents the response from a database request.
+type CosmosDatabaseResponse struct {
+	// DatabaseProperties contains the unmarshalled response body in CosmosDatabaseProperties format.
+	DatabaseProperties *CosmosDatabaseProperties
+	CosmosResponse
+}
+
+func newCosmosDatabaseResponse(resp *http.Response, database *CosmosDatabase) (CosmosDatabaseResponse, error) {
+	response := CosmosDatabaseResponse{}
+	response.RawResponse = resp
+	properties := &CosmosDatabaseProperties{}
+	err := azruntime.UnmarshalAsJSON(resp, properties)
+	if err != nil {
+		return response, err
+	}
+	response.DatabaseProperties = properties
+	response.DatabaseProperties.Database = database
+	return response, nil
+}
diff --git a/sdk/data/azcosmos/cosmos_error.go b/sdk/data/azcosmos/cosmos_error.go
new file mode 100644
index 0000000000..aefc0e6087
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_error.go
@@ -0,0 +1,81 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+)
+
+// cosmosError is used as base error for any error response from the Cosmos service.
+type cosmosError struct {
+	body        string
+	code        string
+	rawResponse *http.Response
+}
+
+func (e *cosmosError) StatusCode() int {
+	if e.rawResponse == nil {
+		return 0
+	}
+	return e.rawResponse.StatusCode
+}
+
+func (e *cosmosError) ErrorCode() string {
+	return e.code
+}
+
+func (e *cosmosError) RawResponse() *http.Response {
+	return e.rawResponse
+}
+
+func newCosmosError(response *http.Response) error {
+	bytesRead, err := azruntime.Payload(response)
+	if err != nil {
+		return err
+	}
+
+	cError := cosmosError{
+		rawResponse: response,
+		body:        string(bytesRead),
+	}
+
+	// Attempt to extract Code from body
+	var cErrorResponse cosmosErrorResponse
+	err = json.Unmarshal(bytesRead, &cErrorResponse)
+	if err == nil {
+		cError.code = cErrorResponse.Code
+	}
+
+	return &cError
+}
+
+func newCosmosErrorWithStatusCode(statusCode int, requestCharge *float32) error {
+	rawResponse := &http.Response{
+		StatusCode: statusCode,
+		Header:     http.Header{},
+	}
+
+	if requestCharge != nil {
+		rawResponse.Header.Add(cosmosHeaderRequestCharge, fmt.Sprint(*requestCharge))
+	}
+
+	return &cosmosError{
+		rawResponse: rawResponse,
+	}
+}
+
+func (e *cosmosError) Error() string {
+	if e.body == "" {
+		return "response contained no body"
+	}
+	return e.body
+}
+
+type cosmosErrorResponse struct {
+	Code string `json:"Code"`
+}
diff --git a/sdk/data/azcosmos/cosmos_headers.go b/sdk/data/azcosmos/cosmos_headers.go
new file mode 100644
index 0000000000..4747b500e1
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_headers.go
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+const (
+	cosmosHeaderRetryAfter             string = "x-ms-retryafter"
+	cosmosHeaderRequestCharge          string = "x-ms-request-charge"
+	cosmosHeaderActivityId             string = "x-ms-activity-id"
+	cosmosHeaderEtag                   string = "etag"
+	cosmosHeaderPopulateQuotaInfo      string = "x-ms-documentdb-populatequotainfo"
+	cosmosHeaderPreTriggerInclude      string = "x-ms-documentdb-pre-trigger-include"
+	cosmosHeaderPostTriggerInclude     string = "x-ms-documentdb-post-trigger-include"
+	cosmosHeaderIndexingDirective      string = "x-ms-indexing-directive"
+	cosmosHeaderSessionToken           string = "x-ms-session-token"
+	cosmosHeaderConsistencyLevel       string = "x-ms-consistency-level"
+	cosmosHeaderPartitionKey           string = "x-ms-documentdb-partitionkey"
+	cosmosHeaderPrefer                 string = "Prefer"
+	cosmosHeaderIsUpsert               string = "x-ms-documentdb-is-upsert"
+	cosmosHeaderOfferThroughput        string = "x-ms-offer-throughput"
+	cosmosHeaderOfferAutoscale         string = "x-ms-cosmos-offer-autopilot-settings"
+	cosmosHeaderQuery                  string = "x-ms-documentdb-query"
+	cosmosHeaderOfferReplacePending    string = "x-ms-offer-replace-pending"
+	cosmosHeaderOfferMinimumThroughput string = "x-ms-cosmos-min-throughput"
+	headerXmsDate                      string = "x-ms-date"
+	headerAuthorization                string = "Authorization"
+	headerContentType                  string = "Content-Type"
+	headerIfMatch                      string = "If-Match"
+	headerIfNoneMatch                  string = "If-None-Match"
+	headerXmsVersion                   string = "x-ms-version"
+)
+
+const (
+	cosmosHeaderValuesPreferMinimal string = "return=minimal"
+	cosmosHeaderValuesQuery         string = "application/query+json"
+)
diff --git a/sdk/data/azcosmos/cosmos_item_request_options.go b/sdk/data/azcosmos/cosmos_item_request_options.go
new file mode 100644
index 0000000000..d584b6b6f9
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_item_request_options.go
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import "strings"
+
+// CosmosItemRequestOptions includes options for operations on items.
+type CosmosItemRequestOptions struct {
+	// Triggers to be invoked before the operation.
+	PreTriggers []string
+	// Triggers to be invoked after the operation.
+	PostTriggers []string
+	// SessionToken to be used when using Session consistency on the account.
+	// When working with Session consistency, each new write request to Azure Cosmos DB is assigned a new SessionToken.
+	// The client instance will use this token internally with each read/query request to ensure that the set consistency level is maintained.
+	// In some scenarios you need to manage this Session yourself: Consider a web application with multiple nodes, each node will have its own client instance.
+	// If you wanted these nodes to participate in the same session (to be able read your own writes consistently across web tiers),
+	// you would have to send the SessionToken from the response of the write action on one node to the client tier, using a cookie or some other mechanism, and have that token flow back to the web tier for subsequent reads.
+	// If you are using a round-robin load balancer which does not maintain session affinity between requests, such as the Azure Load Balancer,the read could potentially land on a different node to the write request, where the session was created.
+	SessionToken string
+	// ConsistencyLevel overrides the account defined consistency level for this operation.
+	// Consistency can only be relaxed.
+	ConsistencyLevel *ConsistencyLevel
+	// Indexing directive to be applied to the operation.
+	IndexingDirective *IndexingDirective
+	// When EnableContentResponseOnWrite is false will cause the response on write operations to have a null resource. This reduces networking and CPU load by not sending the resource back over the network and serializing it on the client.
+	// The default is false.
+	EnableContentResponseOnWrite bool
+}
+
+func (options *CosmosItemRequestOptions) toHeaders() *map[string]string {
+	headers := make(map[string]string)
+
+	if options.PreTriggers != nil && len(options.PreTriggers) > 0 {
+		headers[cosmosHeaderPreTriggerInclude] = strings.Join(options.PreTriggers, ",")
+	}
+
+	if options.PostTriggers != nil && len(options.PostTriggers) > 0 {
+		headers[cosmosHeaderPostTriggerInclude] = strings.Join(options.PostTriggers, ",")
+	}
+
+	if options.ConsistencyLevel != nil {
+		headers[cosmosHeaderConsistencyLevel] = string(*options.ConsistencyLevel)
+	}
+
+	if options.IndexingDirective != nil {
+		headers[cosmosHeaderIndexingDirective] = string(*options.IndexingDirective)
+	}
+
+	if options.SessionToken != "" {
+		headers[cosmosHeaderSessionToken] = options.SessionToken
+	}
+
+	return &headers
+}
diff --git a/sdk/data/azcosmos/cosmos_item_response.go b/sdk/data/azcosmos/cosmos_item_response.go
new file mode 100644
index 0000000000..c795de7668
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_item_response.go
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"net/http"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+)
+
+// CosmosItemResponse represents the response from an item request.
+type CosmosItemResponse struct {
+	// The byte content of the operation response.
+	Value []byte
+	CosmosResponse
+}
+
+// SessionToken contains the value from the session token header to be used on session consistency.
+func (c *CosmosItemResponse) SessionToken() string {
+	return c.RawResponse.Header.Get(cosmosHeaderSessionToken)
+}
+
+func newCosmosItemResponse(resp *http.Response) (CosmosItemResponse, error) {
+	response := CosmosItemResponse{}
+	defer resp.Body.Close()
+	response.RawResponse = resp
+	body, err := azruntime.Payload(resp)
+	if err != nil {
+		return response, err
+	}
+	response.Value = body
+	return response, nil
+}
diff --git a/sdk/data/azcosmos/cosmos_offers.go b/sdk/data/azcosmos/cosmos_offers.go
new file mode 100644
index 0000000000..766c74feb3
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_offers.go
@@ -0,0 +1,121 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+)
+
+type cosmosOffers struct {
+	connection *cosmosClientConnection
+}
+
+type cosmosOffersResponse struct {
+	Offers []ThroughputProperties `json:"Offers"`
+}
+
+func (c cosmosOffers) ReadThroughputIfExists(
+	ctx context.Context,
+	targetRID string,
+	requestOptions *ThroughputRequestOptions) (ThroughputResponse, error) {
+	// TODO: might want to replace with query iterator once that is in
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeOffer,
+		resourceAddress: "",
+	}
+
+	path, err := generatePathForNameBased(resourceTypeOffer, "", true)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	azResponse, err := c.connection.sendQueryRequest(
+		path,
+		ctx,
+		fmt.Sprintf(`SELECT * FROM c WHERE c.offerResourceId = '%s'`, targetRID),
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	var theOffers cosmosOffersResponse
+	err = azruntime.UnmarshalAsJSON(azResponse, &theOffers)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	queryRequestCharge := (&CosmosResponse{RawResponse: azResponse}).RequestCharge()
+	if len(theOffers.Offers) == 0 {
+		return ThroughputResponse{}, newCosmosErrorWithStatusCode(http.StatusNotFound, &queryRequestCharge)
+	}
+
+	// Now read the individual offer
+	operationContext = cosmosOperationContext{
+		resourceType:    resourceTypeOffer,
+		resourceAddress: theOffers.Offers[0].offerId,
+		isRidBased:      true,
+	}
+
+	path, err = generatePathForNameBased(resourceTypeOffer, theOffers.Offers[0].selfLink, false)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	azResponse, err = c.connection.sendGetRequest(
+		path,
+		ctx,
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	return newThroughputResponse(azResponse, &queryRequestCharge)
+}
+
+func (c cosmosOffers) ReplaceThroughputIfExists(
+	ctx context.Context,
+	properties ThroughputProperties,
+	targetRID string,
+	requestOptions *ThroughputRequestOptions) (ThroughputResponse, error) {
+
+	readResponse, err := c.ReadThroughputIfExists(ctx, targetRID, requestOptions)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	readRequestCharge := readResponse.RequestCharge()
+	readResponse.ThroughputProperties.offer = properties.offer
+
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeOffer,
+		resourceAddress: readResponse.ThroughputProperties.offerId,
+		isRidBased:      true,
+	}
+
+	path, err := generatePathForNameBased(resourceTypeOffer, readResponse.ThroughputProperties.selfLink, false)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	azResponse, err := c.connection.sendPutRequest(
+		path,
+		ctx,
+		readResponse.ThroughputProperties,
+		operationContext,
+		requestOptions,
+		nil)
+	if err != nil {
+		return ThroughputResponse{}, err
+	}
+
+	return newThroughputResponse(azResponse, &readRequestCharge)
+}
diff --git a/sdk/data/azcosmos/cosmos_operation_context.go b/sdk/data/azcosmos/cosmos_operation_context.go
new file mode 100644
index 0000000000..49692a4b28
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_operation_context.go
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+type cosmosOperationContext struct {
+	resourceType    resourceType
+	resourceAddress string
+	isRidBased      bool
+}
diff --git a/sdk/data/azcosmos/cosmos_paths.go b/sdk/data/azcosmos/cosmos_paths.go
new file mode 100644
index 0000000000..7bf03fa767
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_paths.go
@@ -0,0 +1,173 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"errors"
+	"fmt"
+	"net/url"
+	"strings"
+)
+
+const (
+	pathSegmentDatabase            string = "dbs"
+	pathSegmentCollection          string = "colls"
+	pathSegmentUser                string = "users"
+	pathSegmentPermission          string = "permissions"
+	pathSegmentStoredProcedure     string = "sprocs"
+	pathSegmentTrigger             string = "triggers"
+	pathSegmentUserDefinedFunction string = "udfs"
+	pathSegmentConflict            string = "conflicts"
+	pathSegmentDocument            string = "docs"
+	pathSegmentClientEncryptionKey string = "clientencryptionkeys"
+	pathSegmentOffer               string = "offers"
+	pathSegmentDatabaseAccount     string = "databaseaccount"
+	pathSegmentPartitionKeyRange   string = "pkranges"
+)
+
+// generatePathForNameBased generates the URL path for a request based on the current operation
+func generatePathForNameBased(resourceType resourceType, ownerOrResourceId string, isFeed bool) (string, error) {
+	if isFeed && ownerOrResourceId == "" &&
+		resourceType != resourceTypeDatabase &&
+		resourceType != resourceTypeOffer &&
+		resourceType != resourceTypeDatabaseAccount {
+		return "", errors.New("INVALID resource type")
+	}
+
+	if resourceType == resourceTypeDatabase {
+		if isFeed {
+			return pathSegmentDatabase, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeCollection {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentCollection, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeOffer {
+		if isFeed {
+			return pathSegmentOffer, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeStoredProcedure {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentStoredProcedure, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeUserDefinedFunction {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentUserDefinedFunction, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeTrigger {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentTrigger, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeConflict {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentConflict, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypePartitionKeyRange {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentPartitionKeyRange, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeUser {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentUser, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypePermission {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentPermission, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeDocument {
+		if isFeed {
+			return ownerOrResourceId + "/" + pathSegmentDocument, nil
+		}
+		return ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeDatabaseAccount {
+		return pathSegmentDatabaseAccount + "/" + ownerOrResourceId, nil
+	}
+
+	if resourceType == resourceTypeClientEncryptionKey {
+		return ownerOrResourceId, nil
+	}
+
+	return "", fmt.Errorf("INVALID resource type %v, isFeed %v, resourceId %v", resourceType, isFeed, ownerOrResourceId)
+}
+
+// getResourcePath is used in auth flows.
+func getResourcePath(resourceType resourceType) (string, error) {
+	switch resourceType {
+	case resourceTypeDatabase:
+		return pathSegmentDatabase, nil
+	case resourceTypeCollection:
+		return pathSegmentCollection, nil
+	case resourceTypeDocument:
+		return pathSegmentDocument, nil
+	case resourceTypeDatabaseAccount:
+		return pathSegmentDatabaseAccount, nil
+	case resourceTypeOffer:
+		return pathSegmentOffer, nil
+	case resourceTypeUser:
+		return pathSegmentUser, nil
+	case resourceTypeStoredProcedure:
+		return pathSegmentStoredProcedure, nil
+	case resourceTypeUserDefinedFunction:
+		return pathSegmentUserDefinedFunction, nil
+	case resourceTypeTrigger:
+		return pathSegmentTrigger, nil
+	case resourceTypePermission:
+		return pathSegmentPermission, nil
+	case resourceTypeConflict:
+		return pathSegmentConflict, nil
+	case resourceTypePartitionKeyRange:
+		return pathSegmentPartitionKeyRange, nil
+	case resourceTypeClientEncryptionKey:
+		return pathSegmentClientEncryptionKey, nil
+	default:
+		return "", fmt.Errorf("%v is not a valid resource type", resourceType)
+	}
+}
+
+// createLink generates a url link for a resource base on the parent paths
+func createLink(parentPath string, pathSegment string, id string) string {
+	var completePath strings.Builder
+	parentPathLength := len(parentPath)
+	completePath.Grow(parentPathLength + 2 + len(pathSegment) + len(id))
+	if parentPathLength > 0 {
+		completePath.WriteString(parentPath)
+		completePath.WriteString("/")
+	}
+	completePath.WriteString(pathSegment)
+	completePath.WriteString("/")
+	completePath.WriteString(url.QueryEscape(id))
+	return completePath.String()
+}
diff --git a/sdk/data/azcosmos/cosmos_request_options.go b/sdk/data/azcosmos/cosmos_request_options.go
new file mode 100644
index 0000000000..ac1d6d8c97
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_request_options.go
@@ -0,0 +1,8 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+type cosmosRequestOptions interface {
+	toHeaders() *map[string]string
+}
diff --git a/sdk/data/azcosmos/cosmos_response.go b/sdk/data/azcosmos/cosmos_response.go
new file mode 100644
index 0000000000..87d646d3e1
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_response.go
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"net/http"
+	"strconv"
+)
+
+// CosmosResponse is the base response type for all responses from the Azure Cosmos DB database service.
+// It contains base methods and properties that are common to all responses.
+type CosmosResponse struct {
+	// RawResponse contains the underlying HTTP response.
+	RawResponse *http.Response
+}
+
+// RequestCharge contains the value from the request charge header.
+func (c *CosmosResponse) RequestCharge() float32 {
+	requestChargeString := c.RawResponse.Header.Get(cosmosHeaderRequestCharge)
+	if requestChargeString == "" {
+		return 0
+	}
+	f, err := strconv.ParseFloat(requestChargeString, 32)
+	if err != nil {
+		return 0
+	}
+	return float32(f)
+}
+
+// ActivityId contains the value from the activity header.
+func (c *CosmosResponse) ActivityId() string {
+	return c.RawResponse.Header.Get(cosmosHeaderActivityId)
+}
+
+// ETag contains the value from the ETag header.
+func (c *CosmosResponse) ETag() string {
+	return c.RawResponse.Header.Get(cosmosHeaderEtag)
+}
diff --git a/sdk/data/azcosmos/data_type.go b/sdk/data/azcosmos/data_type.go
new file mode 100644
index 0000000000..2d8daa2296
--- /dev/null
+++ b/sdk/data/azcosmos/data_type.go
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// DataType defines supported values for data types in Spatial Indexes
+type DataType string
+
+const (
+	// Represents a line.
+	DataTypeString DataType = "String"
+	// Represents a number.
+	DataTypeNumber DataType = "Number"
+	// Represents a point.
+	DataTypePoint DataType = "Point"
+	// Represents a polygon.
+	DataTypePolygon DataType = "Polygon"
+	// Represents a line string.
+	DataTypeLineString DataType = "LineString"
+	// Represents a multi polygon.
+	DataTypeMultiPolygon DataType = "MultiPolygon"
+)
+
+// Returns a list of available data types
+func DataTypeValues() []DataType {
+	return []DataType{DataTypeString, DataTypeNumber, DataTypePoint, DataTypePolygon, DataTypeLineString, DataTypeMultiPolygon}
+}
+
+func (c DataType) ToPtr() *DataType {
+	return &c
+}
diff --git a/sdk/data/azcosmos/doc.go b/sdk/data/azcosmos/doc.go
new file mode 100644
index 0000000000..0570d150d9
--- /dev/null
+++ b/sdk/data/azcosmos/doc.go
@@ -0,0 +1,8 @@
+// Copyright 2021 Microsoft Corporation. All rights reserved.
+// Use of this source code is governed by an MIT
+// license that can be found in the LICENSE file.
+
+/*
+Package azcosmos implements the client to interact with the Azure Cosmos DB SQL API.
+*/
+package azcosmos
diff --git a/sdk/data/azcosmos/go.mod b/sdk/data/azcosmos/go.mod
new file mode 100644
index 0000000000..e7b91b9707
--- /dev/null
+++ b/sdk/data/azcosmos/go.mod
@@ -0,0 +1,10 @@
+module github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos
+
+go 1.16
+
+require (
+	github.com/Azure/azure-sdk-for-go v57.3.0+incompatible
+	github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0
+	github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0
+	github.com/stretchr/testify v1.7.0
+)
diff --git a/sdk/data/azcosmos/go.sum b/sdk/data/azcosmos/go.sum
new file mode 100644
index 0000000000..df703095a2
--- /dev/null
+++ b/sdk/data/azcosmos/go.sum
@@ -0,0 +1,31 @@
+github.com/Azure/azure-sdk-for-go v57.3.0+incompatible h1:zxuxvsRYSXcowMuT/P5b7o6YJYuGYP74jCb9IvlgOLA=
+github.com/Azure/azure-sdk-for-go v57.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0 h1:lhSJz9RMbJcTgxifR1hUNJnn6CNYtbgEDtQV22/9RBA=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
+github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0 h1:v9p9TfTbf7AwNb5NYQt7hI41IfPoLFiFkLtb+bmGjT0=
+github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
+github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A=
+golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/sdk/data/azcosmos/go_mod_tidy_hack.go b/sdk/data/azcosmos/go_mod_tidy_hack.go
new file mode 100644
index 0000000000..746e3271e0
--- /dev/null
+++ b/sdk/data/azcosmos/go_mod_tidy_hack.go
@@ -0,0 +1,13 @@
+//go:build modhack
+// +build modhack
+
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+// This file, and the github.com/Azure/azure-sdk-for-go import, won't actually become part of
+// the resultant binary.
+
+package azcosmos
+
+// Necessary for safely adding multi-module repo. See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository
+import _ "github.com/Azure/azure-sdk-for-go"
diff --git a/sdk/data/azcosmos/indexing_directive.go b/sdk/data/azcosmos/indexing_directive.go
new file mode 100644
index 0000000000..0e90e57cd9
--- /dev/null
+++ b/sdk/data/azcosmos/indexing_directive.go
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// Specifies whether or not the resource in the Azure Cosmos DB database is to be indexed.
+type IndexingDirective string
+
+const (
+	// Use any pre-defined/pre-configured defaults.
+	IndexingDirectiveDefault IndexingDirective = "Default"
+	// Index the resource.
+	IndexingDirectiveInclude IndexingDirective = "Include"
+	// Do not index the resource.
+	IndexingDirectiveExclude IndexingDirective = "Exclude"
+)
+
+// Returns a list of available indexing directives
+func IndexingDirectives() []IndexingDirective {
+	return []IndexingDirective{IndexingDirectiveDefault, IndexingDirectiveInclude, IndexingDirectiveExclude}
+}
+
+func (c IndexingDirective) ToPtr() *IndexingDirective {
+	return &c
+}
diff --git a/sdk/data/azcosmos/indexing_mode.go b/sdk/data/azcosmos/indexing_mode.go
new file mode 100644
index 0000000000..2b6080c288
--- /dev/null
+++ b/sdk/data/azcosmos/indexing_mode.go
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// IndexingMode defines the supported indexing modes in the Azure Cosmos DB service.
+type IndexingMode string
+
+const (
+	// IndexingModeConsistent Index is updated synchronously with a create, update or delete operation.
+	IndexingModeConsistent IndexingMode = "Consistent"
+	// No index is provided.
+	IndexingModeNone IndexingMode = "None"
+)
+
+// Returns a list of available consistency levels
+func IndexingModeValues() []IndexingMode {
+	return []IndexingMode{IndexingModeConsistent, IndexingModeNone}
+}
+
+func (c IndexingMode) ToPtr() *IndexingMode {
+	return &c
+}
diff --git a/sdk/data/azcosmos/indexing_policy.go b/sdk/data/azcosmos/indexing_policy.go
new file mode 100644
index 0000000000..9d050beb96
--- /dev/null
+++ b/sdk/data/azcosmos/indexing_policy.go
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// IndexingPolicy represents an indexing policy for a container.
+// For more information see https://docs.microsoft.com/azure/cosmos-db/index-policy
+type IndexingPolicy struct {
+	// Automatic defines if the indexing policy is automatic or manual.
+	Automatic bool `json:"automatic"`
+	// IndexingMode for the container.
+	IndexingMode IndexingMode `json:"indexingMode,omitempty"`
+	// Paths to be indexed.
+	IncludedPaths []IncludedPath `json:"includedPaths,omitempty"`
+	// Paths to be excluded.
+	ExcludedPaths []ExcludedPath `json:"excludedPaths,omitempty"`
+	// Spatial indexes.
+	SpatialIndexes []SpatialIndex `json:"spatialIndexes,omitempty"`
+	// Spatial indexes.
+	CompositeIndexes [][]CompositeIndex `json:"compositeIndexes,omitempty"`
+}
+
+// IncludedPath represents a json path to be included in indexing.
+type IncludedPath struct {
+	// Path to be included.
+	Path string `json:"path"`
+}
+
+// ExcludedPath represents a json path to be excluded from indexing.
+type ExcludedPath struct {
+	// Path to be excluded.
+	Path string `json:"path"`
+}
+
+// SpatialIndex represents a spatial index.
+type SpatialIndex struct {
+	// Path for the index.
+	Path string `json:"path"`
+	// SpatialType of the spatial index.
+	SpatialTypes []SpatialType `json:"types"`
+}
+
+type CompositeIndex struct {
+	// Path for the index.
+	Path string `json:"path"`
+	// Order represents the order of the composite index.
+	// For example if you want to run the query "SELECT * FROM c ORDER BY c.age asc, c.height desc",
+	// then you need to make the order for "/age" "ascending" and the order for "/height" "descending".
+	Order CompositeIndexOrder `json:"order"`
+}
diff --git a/sdk/data/azcosmos/partition_key.go b/sdk/data/azcosmos/partition_key.go
new file mode 100644
index 0000000000..dfad7db1ea
--- /dev/null
+++ b/sdk/data/azcosmos/partition_key.go
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import "encoding/json"
+
+// PartitionKey represents a logical partition key value.
+type PartitionKey struct {
+	isNone               bool
+	partitionKeyInternal *partitionKeyInternal
+}
+
+// NewPartitionKeyNone creates a partition key value for non-partitioned containers.
+func NewPartitionKeyNone() *PartitionKey {
+	return &PartitionKey{
+		isNone:               true,
+		partitionKeyInternal: nonePartitionKey,
+	}
+}
+
+// NewPartitionKey creates a new partition key.
+// value - the partition key value.
+func NewPartitionKey(value interface{}) (*PartitionKey, error) {
+	pkInternal, err := newPartitionKeyInternal([]interface{}{value})
+	if err != nil {
+		return nil, err
+	}
+	return &PartitionKey{
+		partitionKeyInternal: pkInternal,
+		isNone:               false,
+	}, nil
+}
+
+func (pk *PartitionKey) toJsonString() (string, error) {
+	if pk.isNone {
+		return "", nil
+	}
+
+	res, err := json.Marshal(pk.partitionKeyInternal)
+	if err != nil {
+		return "", err
+	}
+	return string(res), nil
+}
diff --git a/sdk/data/azcosmos/partition_key_definition.go b/sdk/data/azcosmos/partition_key_definition.go
new file mode 100644
index 0000000000..65268d81da
--- /dev/null
+++ b/sdk/data/azcosmos/partition_key_definition.go
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// PartitionKeyDefinition represents a partition key definition in the Azure Cosmos DB database service.
+// A partition key definition defines the path for the partition key property.
+type PartitionKeyDefinition struct {
+	// Paths returns the list of partition key paths of the container.
+	Paths []string `json:"paths"`
+	// Version returns the version of the hash partitioning of the container.
+	Version PartitionKeyDefinitionVersion `json:"version,omitempty"`
+}
diff --git a/sdk/data/azcosmos/partition_key_definition_version.go b/sdk/data/azcosmos/partition_key_definition_version.go
new file mode 100644
index 0000000000..2e5db610ec
--- /dev/null
+++ b/sdk/data/azcosmos/partition_key_definition_version.go
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// Version of the hash partitioning
+type PartitionKeyDefinitionVersion int
+
+const (
+	// Original version of hash partitioning.
+	PartitionKeyDefinitionVersion1 PartitionKeyDefinitionVersion = 1
+	// Enhanced version of hash partitioning - offers better distribution of long partition keys and uses less storage.
+	PartitionKeyDefinitionVersion2 PartitionKeyDefinitionVersion = 2
+)
+
+// Returns a list of available consistency levels
+func PartitionKeyDefinitionVersionValues() []PartitionKeyDefinitionVersion {
+	return []PartitionKeyDefinitionVersion{PartitionKeyDefinitionVersion1, PartitionKeyDefinitionVersion2}
+}
+
+func (c PartitionKeyDefinitionVersion) ToPtr() *PartitionKeyDefinitionVersion {
+	return &c
+}
diff --git a/sdk/data/azcosmos/partition_key_internal.go b/sdk/data/azcosmos/partition_key_internal.go
new file mode 100644
index 0000000000..fc54861453
--- /dev/null
+++ b/sdk/data/azcosmos/partition_key_internal.go
@@ -0,0 +1,104 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+var (
+	nonePartitionKey      = &partitionKeyInternal{components: nil}
+	emptyPartitionKey     = &partitionKeyInternal{components: []interface{}{}}
+	undefinedPartitionKey = &partitionKeyInternal{components: []interface{}{&partitionKeyUndefinedComponent{}}}
+)
+
+type partitionKeyInternal struct {
+	components []interface{}
+}
+
+func newPartitionKeyInternal(values []interface{}) (*partitionKeyInternal, error) {
+	components := make([]interface{}, len(values))
+	for i, v := range values {
+		var component interface{}
+		switch val := v.(type) {
+		case nil:
+			component = &partitionKeyNullComponent{}
+		case bool:
+			component = &partitionKeyBoolComponent{val}
+		case string:
+			component = &partitionKeyStringComponent{val}
+		case int:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case int8:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case int16:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case int32:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case int64:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case uint:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case uint8:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case uint16:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case uint32:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case uint64:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case float32:
+			component = &partitionKeyNumberComponent{float64(val)}
+		case float64:
+			component = &partitionKeyNumberComponent{val}
+		default:
+			return nil, fmt.Errorf("PartitionKey can only be a string, bool, or a number: '%T'", v)
+		}
+
+		components[i] = component
+	}
+
+	return &partitionKeyInternal{components: components}, nil
+}
+
+func (p *partitionKeyInternal) MarshalJSON() ([]byte, error) {
+	return json.Marshal(p.components)
+}
+
+type partitionKeyNumberComponent struct {
+	value float64
+}
+
+func (p *partitionKeyNumberComponent) MarshalJSON() ([]byte, error) {
+	return json.Marshal(p.value)
+}
+
+type partitionKeyBoolComponent struct {
+	value bool
+}
+
+func (p *partitionKeyBoolComponent) MarshalJSON() ([]byte, error) {
+	return json.Marshal(p.value)
+}
+
+type partitionKeyStringComponent struct {
+	value string
+}
+
+func (p *partitionKeyStringComponent) MarshalJSON() ([]byte, error) {
+	return json.Marshal(p.value)
+}
+
+type partitionKeyNullComponent struct{}
+
+func (p *partitionKeyNullComponent) MarshalJSON() ([]byte, error) {
+	return []byte("null"), nil
+}
+
+type partitionKeyUndefinedComponent struct{}
+
+func (p *partitionKeyUndefinedComponent) MarshalJSON() ([]byte, error) {
+	return []byte("{}"), nil
+}
diff --git a/sdk/data/azcosmos/resource_throttle_retry_policy.go b/sdk/data/azcosmos/resource_throttle_retry_policy.go
new file mode 100644
index 0000000000..c27566857c
--- /dev/null
+++ b/sdk/data/azcosmos/resource_throttle_retry_policy.go
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"net/http"
+	"time"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
+)
+
+const (
+	defaultResourceThrottleRetryPolicyMaxWaitTime time.Duration = 60 * time.Second
+	defaultResourceThrottleRetryPolicyRetryCount  int           = 9
+)
+
+// resourceThrottleRetryPolicy retries on HTTP 429.
+type resourceThrottleRetryPolicy struct {
+	MaxWaitTime   time.Duration
+	MaxRetryCount int
+}
+
+func newResourceThrottleRetryPolicy(o *CosmosClientOptions) *resourceThrottleRetryPolicy {
+	if o.RateLimitedRetry == nil {
+		return &resourceThrottleRetryPolicy{
+			MaxWaitTime:   defaultResourceThrottleRetryPolicyMaxWaitTime,
+			MaxRetryCount: defaultResourceThrottleRetryPolicyRetryCount}
+	}
+
+	return &resourceThrottleRetryPolicy{
+		MaxWaitTime:   o.RateLimitedRetry.MaxRetryWaitTime,
+		MaxRetryCount: o.RateLimitedRetry.MaxRetryAttempts}
+}
+
+func (p *resourceThrottleRetryPolicy) Do(req *policy.Request) (*http.Response, error) {
+	// Policy disabled
+	if p.MaxRetryCount == 0 {
+		return req.Next()
+	}
+
+	var resp *http.Response
+	var err error
+	var cumulativeWaitTime time.Duration
+	for attempts := 0; attempts < p.MaxRetryCount; attempts++ {
+		err = req.RewindBody()
+		if err != nil {
+			return resp, err
+		}
+
+		resp, err = req.Next()
+		if err != nil || resp.StatusCode != http.StatusTooManyRequests {
+			return resp, err
+		}
+
+		retryAfter := resp.Header.Get(cosmosHeaderRetryAfter)
+		retryAfterDuration := parseRetryAfter(retryAfter)
+		cumulativeWaitTime += retryAfterDuration
+
+		if retryAfterDuration > p.MaxWaitTime || cumulativeWaitTime > p.MaxWaitTime {
+			return resp, err
+		}
+
+		// drain before retrying so nothing is leaked
+		azruntime.Drain(resp)
+
+		select {
+		case <-time.After(retryAfterDuration):
+			// retry
+		case <-req.Raw().Context().Done():
+			err = req.Raw().Context().Err()
+			log.Writef(log.RetryPolicy, "ResourceThrottleRetryPolicy abort due to %v", err)
+			return resp, err
+		}
+	}
+
+	return resp, err
+}
+
+func parseRetryAfter(retryAfter string) time.Duration {
+	if retryAfter == "" {
+		return 0
+	}
+
+	retryAfterDuration, err := time.ParseDuration(retryAfter + "ms")
+	if err != nil {
+		return 0
+	}
+
+	return retryAfterDuration
+}
diff --git a/sdk/data/azcosmos/resource_type.go b/sdk/data/azcosmos/resource_type.go
new file mode 100644
index 0000000000..6cc5317621
--- /dev/null
+++ b/sdk/data/azcosmos/resource_type.go
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// resourceType defines supported values for resources.
+type resourceType int
+
+const (
+	resourceTypeDatabase            resourceType = 0
+	resourceTypeCollection          resourceType = 1
+	resourceTypeDocument            resourceType = 2
+	resourceTypeUser                resourceType = 4
+	resourceTypePermission          resourceType = 5
+	resourceTypeConflict            resourceType = 107
+	resourceTypeStoredProcedure     resourceType = 109
+	resourceTypeTrigger             resourceType = 110
+	resourceTypeUserDefinedFunction resourceType = 111
+	resourceTypeOffer               resourceType = 113
+	resourceTypeDatabaseAccount     resourceType = 118
+	resourceTypePartitionKeyRange   resourceType = 125
+	resourceTypeClientEncryptionKey resourceType = 141
+)
diff --git a/sdk/data/azcosmos/shared_key_credential.go b/sdk/data/azcosmos/shared_key_credential.go
new file mode 100644
index 0000000000..8455471d47
--- /dev/null
+++ b/sdk/data/azcosmos/shared_key_credential.go
@@ -0,0 +1,136 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/base64"
+	"fmt"
+	"net/http"
+	"net/url"
+	"strings"
+	"sync/atomic"
+	"time"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
+)
+
+// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the
+// account's primary or secondary key.
+func NewSharedKeyCredential(accountKey string) (*SharedKeyCredential, error) {
+	c := SharedKeyCredential{}
+	if err := c.SetAccountKey(accountKey); err != nil {
+		return nil, err
+	}
+	return &c, nil
+}
+
+// SharedKeyCredential contains an account's name and its primary or secondary key.
+// It is immutable making it shareable and goroutine-safe.
+type SharedKeyCredential struct {
+	// Only the NewSharedKeyCredential method should set these; all other methods should treat them as read-only
+	accountKey atomic.Value // []byte
+}
+
+// SetAccountKey replaces the existing account key with the specified account key.
+func (c *SharedKeyCredential) SetAccountKey(accountKey string) error {
+	bytes, err := base64.StdEncoding.DecodeString(accountKey)
+	if err != nil {
+		return fmt.Errorf("decode account key: %w", err)
+	}
+	c.accountKey.Store(bytes)
+	return nil
+}
+
+// computeHMACSHA256 generates a hash signature for an HTTP request
+func (c *SharedKeyCredential) computeHMACSHA256(s string) (base64String string) {
+	h := hmac.New(sha256.New, c.accountKey.Load().([]byte))
+	_, _ = h.Write([]byte(s))
+	return base64.StdEncoding.EncodeToString(h.Sum(nil))
+}
+
+func (c *SharedKeyCredential) buildCanonicalizedAuthHeaderFromRequest(req *policy.Request) (string, error) {
+	var opValues cosmosOperationContext
+	value := ""
+
+	if req.OperationValue(&opValues) {
+		resourceTypePath, err := getResourcePath(opValues.resourceType)
+
+		if err != nil {
+			return "", err
+		}
+
+		resourceAddress := opValues.resourceAddress
+		if opValues.isRidBased {
+			resourceAddress = strings.ToLower(resourceAddress)
+		}
+
+		value = c.buildCanonicalizedAuthHeader(req.Raw().Method, resourceTypePath, resourceAddress, req.Raw().Header.Get(headerXmsDate), "master", "1.0")
+	}
+
+	return value, nil
+}
+
+//where date is like time.RFC1123 but hard-codes GMT as the time zone
+func (c *SharedKeyCredential) buildCanonicalizedAuthHeader(method, resourceType, resourceAddress, xmsDate, tokenType, version string) string {
+	if method == "" || resourceType == "" {
+		return ""
+	}
+
+	// https://docs.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources#constructkeytoken
+	stringToSign := join(strings.ToLower(method), "\n", strings.ToLower(resourceType), "\n", resourceAddress, "\n", strings.ToLower(xmsDate), "\n", "", "\n")
+	signature := c.computeHMACSHA256(stringToSign)
+
+	return url.QueryEscape(join("type=" + tokenType + "&ver=" + version + "&sig=" + signature))
+}
+
+type sharedKeyCredPolicy struct {
+	cred *SharedKeyCredential
+}
+
+func newSharedKeyCredPolicy(cred *SharedKeyCredential, opts runtime.AuthenticationOptions) *sharedKeyCredPolicy {
+	s := &sharedKeyCredPolicy{
+		cred: cred,
+	}
+
+	return s
+}
+
+func (c *SharedKeyCredential) NewAuthenticationPolicy(options runtime.AuthenticationOptions) policy.Policy {
+	return newSharedKeyCredPolicy(c, options)
+}
+
+func (s *sharedKeyCredPolicy) Do(req *policy.Request) (*http.Response, error) {
+	// Add a x-ms-date header if it doesn't already exist
+	if d := req.Raw().Header.Get(headerXmsDate); d == "" {
+		req.Raw().Header.Set(headerXmsDate, time.Now().UTC().Format(http.TimeFormat))
+	}
+
+	authHeader, err := s.cred.buildCanonicalizedAuthHeaderFromRequest(req)
+	if err != nil {
+		return nil, err
+	}
+
+	if authHeader != "" {
+		req.Raw().Header.Set(headerAuthorization, authHeader)
+	}
+
+	response, err := req.Next()
+	if err != nil && response != nil && response.StatusCode == http.StatusForbidden {
+		// Service failed to authenticate request, log it
+		log.Write(log.Response, "===== HTTP Forbidden status, Authorization:\n"+authHeader+"\n=====\n")
+	}
+	return response, err
+}
+
+func join(strs ...string) string {
+	var sb strings.Builder
+	for _, str := range strs {
+		sb.WriteString(str)
+	}
+	return sb.String()
+}
diff --git a/sdk/data/azcosmos/spatial_type.go b/sdk/data/azcosmos/spatial_type.go
new file mode 100644
index 0000000000..42e5ed2b1a
--- /dev/null
+++ b/sdk/data/azcosmos/spatial_type.go
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// SpatialType defines supported values for spatial index types in Spatial Indexes
+type SpatialType string
+
+const (
+	// Represents a point.
+	SpatialTypePoint SpatialType = "Point"
+	// Represents a polygon.
+	SpatialTypePolygon SpatialType = "Polygon"
+	// Represents a line string.
+	SpatialTypeLineString SpatialType = "LineString"
+	// Represents a multi polygon.
+	SpatialTypeMultiPolygon SpatialType = "MultiPolygon"
+)
+
+// Returns a list of available data types
+func SpatialTypeValues() []SpatialType {
+	return []SpatialType{SpatialTypePoint, SpatialTypePolygon, SpatialTypeLineString, SpatialTypeMultiPolygon}
+}
+
+func (c SpatialType) ToPtr() *SpatialType {
+	return &c
+}
diff --git a/sdk/data/azcosmos/throughput_properties.go b/sdk/data/azcosmos/throughput_properties.go
new file mode 100644
index 0000000000..601e2c5b58
--- /dev/null
+++ b/sdk/data/azcosmos/throughput_properties.go
@@ -0,0 +1,248 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"strconv"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+)
+
+const (
+	offerVersion2 string = "V2"
+)
+
+// ThroughputProperties describes the throughput configuration of a resource.
+type ThroughputProperties struct {
+	ETag         string
+	LastModified *UnixTime
+
+	version         string
+	offerType       string
+	offer           *offer
+	offerResourceId string
+	offerId         string
+	selfLink        string
+}
+
+// NewManualThroughputProperties returns a ThroughputProperties object with the given throughput in manual mode.
+// throughput - the throughput in RU/s
+func NewManualThroughputProperties(throughput int) *ThroughputProperties {
+	return &ThroughputProperties{
+		version: offerVersion2,
+		offer:   newManualOffer(throughput),
+	}
+}
+
+// NewAutoscaleThroughputPropertiesWithIncrement returns a ThroughputProperties object with the given max throughput on autoscale mode.
+// maxThroughput - the max throughput in RU/s
+// incrementPercentage - the auto upgrade max throughput increment percentage
+func NewAutoscaleThroughputPropertiesWithIncrement(startingMaxThroughput int, incrementPercentage int) *ThroughputProperties {
+	return &ThroughputProperties{
+		version: offerVersion2,
+		offer:   newAutoscaleOfferWithIncrement(startingMaxThroughput, incrementPercentage),
+	}
+}
+
+// NewAutoscaleThroughputProperties returns a ThroughputProperties object with the given max throughput on autoscale mode.
+// maxThroughput - the max throughput in RU/s
+func NewAutoscaleThroughputProperties(startingMaxThroughput int) *ThroughputProperties {
+	return &ThroughputProperties{
+		version: offerVersion2,
+		offer:   newAutoscaleOffer(startingMaxThroughput),
+	}
+}
+
+func (tp *ThroughputProperties) MarshalJSON() ([]byte, error) {
+	offer, err := json.Marshal(tp.offer)
+	if err != nil {
+		return nil, err
+	}
+
+	buffer := bytes.NewBufferString("{")
+	buffer.WriteString("\"content\":")
+	buffer.Write(offer)
+
+	if tp.offerResourceId != "" {
+		buffer.WriteString(fmt.Sprintf(",\"offerResourceId\":\"%s\"", tp.offerResourceId))
+	}
+
+	if tp.offerId != "" {
+		buffer.WriteString(fmt.Sprintf(",\"id\":\"%s\"", tp.offerId))
+	}
+
+	buffer.WriteString(fmt.Sprintf(",\"offerType\":\"%s\"", tp.offerType))
+	buffer.WriteString(fmt.Sprintf(",\"offerVersion\":\"%s\"", tp.version))
+
+	if tp.ETag != "" {
+		buffer.WriteString(",\"_etag\":")
+		etag, err := json.Marshal(tp.ETag)
+		if err != nil {
+			return nil, err
+		}
+		buffer.Write(etag)
+	}
+
+	if tp.selfLink != "" {
+		buffer.WriteString(fmt.Sprintf(",\"_self\":\"%s\"", tp.selfLink))
+	}
+
+	if tp.LastModified != nil {
+		buffer.WriteString(",\"_ts\":")
+		ts, err := json.Marshal(tp.LastModified)
+		if err != nil {
+			return nil, err
+		}
+		buffer.Write(ts)
+	}
+
+	buffer.WriteString("}")
+	return buffer.Bytes(), nil
+}
+
+func (tp *ThroughputProperties) UnmarshalJSON(b []byte) error {
+	var attributes map[string]json.RawMessage
+	err := json.Unmarshal(b, &attributes)
+	if err != nil {
+		return err
+	}
+
+	if content, ok := attributes["content"]; ok {
+		if err := json.Unmarshal(content, &tp.offer); err != nil {
+			return err
+		}
+	}
+
+	if offerType, ok := attributes["offerType"]; ok {
+		if err := json.Unmarshal(offerType, &tp.offerType); err != nil {
+			return err
+		}
+	}
+
+	if version, ok := attributes["offerVersion"]; ok {
+		if err := json.Unmarshal(version, &tp.version); err != nil {
+			return err
+		}
+	}
+
+	if offerResourceId, ok := attributes["offerResourceId"]; ok {
+		if err := json.Unmarshal(offerResourceId, &tp.offerResourceId); err != nil {
+			return err
+		}
+	}
+
+	if etag, ok := attributes["_etag"]; ok {
+		if err := json.Unmarshal(etag, &tp.ETag); err != nil {
+			return err
+		}
+	}
+
+	if ts, ok := attributes["_ts"]; ok {
+		if err := json.Unmarshal(ts, &tp.LastModified); err != nil {
+			return err
+		}
+	}
+
+	if id, ok := attributes["id"]; ok {
+		if err := json.Unmarshal(id, &tp.offerId); err != nil {
+			return err
+		}
+	}
+
+	if self, ok := attributes["_self"]; ok {
+		if err := json.Unmarshal(self, &tp.selfLink); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// ManualThroughput returns the provisioned throughput in manual mode.
+func (tp *ThroughputProperties) ManualThroughput() (int, error) {
+	if tp.offer.Throughput == nil {
+		return 0, fmt.Errorf("offer is not a manual offer")
+	}
+
+	return *tp.offer.Throughput, nil
+}
+
+// AutoscaleMaxThroughput returns the configured max throughput on autoscale mode.
+func (tp *ThroughputProperties) AutoscaleMaxThroughput() (int, error) {
+	if tp.offer.AutoScale == nil {
+		return 0, fmt.Errorf("offer is not an autoscale offer")
+	}
+
+	return tp.offer.AutoScale.MaxThroughput, nil
+}
+
+func (tp *ThroughputProperties) addHeadersToRequest(req *policy.Request) {
+	if tp == nil {
+		return
+	}
+
+	if tp.offer.Throughput != nil {
+		req.Raw().Header.Add(cosmosHeaderOfferThroughput, strconv.Itoa(*tp.offer.Throughput))
+	} else {
+		req.Raw().Header.Add(cosmosHeaderOfferAutoscale, tp.offer.AutoScale.ToJsonString())
+	}
+}
+
+type offer struct {
+	Throughput *int               `json:"offerThroughput,omitempty"`
+	AutoScale  *autoscaleSettings `json:"offerAutopilotSettings,omitempty"`
+}
+
+func newManualOffer(throughput int) *offer {
+	return &offer{
+		Throughput: &throughput,
+	}
+}
+
+func newAutoscaleOfferWithIncrement(startingMaxThroughput int, incrementPercentage int) *offer {
+	return &offer{
+		AutoScale: &autoscaleSettings{
+			MaxThroughput: startingMaxThroughput,
+			AutoscaleAutoUpgradeProperties: &autoscaleAutoUpgradeProperties{
+				ThroughputPolicy: &autoscaleThroughputPolicy{
+					IncrementPercent: incrementPercentage,
+				},
+			},
+		},
+	}
+}
+
+func newAutoscaleOffer(startingMaxThroughput int) *offer {
+	return &offer{
+		AutoScale: &autoscaleSettings{
+			MaxThroughput: startingMaxThroughput,
+		},
+	}
+}
+
+type autoscaleSettings struct {
+	MaxThroughput                  int                             `json:"maxThroughput,omitempty"`
+	AutoscaleAutoUpgradeProperties *autoscaleAutoUpgradeProperties `json:"autoUpgradePolicy,omitempty"`
+}
+
+func (as *autoscaleSettings) ToJsonString() string {
+	if as == nil {
+		return ""
+	}
+
+	jsonString, _ := json.Marshal(as)
+
+	return string(jsonString)
+}
+
+type autoscaleAutoUpgradeProperties struct {
+	ThroughputPolicy *autoscaleThroughputPolicy `json:"throughputPolicy,omitempty"`
+}
+
+type autoscaleThroughputPolicy struct {
+	IncrementPercent int `json:"incrementPercent,omitempty"`
+}
diff --git a/sdk/data/azcosmos/throughput_request_options.go b/sdk/data/azcosmos/throughput_request_options.go
new file mode 100644
index 0000000000..1509a2ea6e
--- /dev/null
+++ b/sdk/data/azcosmos/throughput_request_options.go
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// ThroughputRequestOptions includes options for throughput operations.
+type ThroughputRequestOptions struct {
+	IfMatchEtag     string
+	IfNoneMatchEtag string
+}
+
+func (options *ThroughputRequestOptions) toHeaders() *map[string]string {
+	if options.IfMatchEtag == "" && options.IfNoneMatchEtag == "" {
+		return nil
+	}
+
+	headers := make(map[string]string)
+	if options.IfMatchEtag != "" {
+		headers[headerIfMatch] = options.IfMatchEtag
+	}
+	if options.IfNoneMatchEtag != "" {
+		headers[headerIfNoneMatch] = options.IfNoneMatchEtag
+	}
+	return &headers
+}
diff --git a/sdk/data/azcosmos/throughput_response.go b/sdk/data/azcosmos/throughput_response.go
new file mode 100644
index 0000000000..8f0a97087e
--- /dev/null
+++ b/sdk/data/azcosmos/throughput_response.go
@@ -0,0 +1,69 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"fmt"
+	"net/http"
+	"strconv"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+)
+
+// ThroughputResponse represents the response from a throughput request.
+type ThroughputResponse struct {
+	// ThroughputProperties contains the unmarshalled response body in ThroughputProperties format.
+	ThroughputProperties *ThroughputProperties
+	CosmosResponse
+}
+
+// IsReplacePending returns the state of a throughput update.
+func (r *ThroughputResponse) IsReplacePending() *bool {
+	isPending := r.RawResponse.Header.Get(cosmosHeaderOfferReplacePending)
+	if isPending == "" {
+		return nil
+	}
+
+	isPendingBool, err := strconv.ParseBool(isPending)
+	if err != nil {
+		return nil
+	}
+
+	return &isPendingBool
+}
+
+// MinThroughput is minimum throughput in measurement of request units per second in the Azure Cosmos service.
+func (r *ThroughputResponse) MinThroughput() *int {
+	minThroughput := r.RawResponse.Header.Get(cosmosHeaderOfferMinimumThroughput)
+	if minThroughput == "" {
+		return nil
+	}
+
+	minThroughputInt, err := strconv.ParseInt(minThroughput, 10, 32)
+	if err != nil {
+		return nil
+	}
+
+	minThroughputAsInt := int(minThroughputInt)
+
+	return &minThroughputAsInt
+}
+
+func newThroughputResponse(resp *http.Response, extraRequestCharge *float32) (ThroughputResponse, error) {
+	response := ThroughputResponse{}
+	response.RawResponse = resp
+	properties := &ThroughputProperties{}
+	err := azruntime.UnmarshalAsJSON(resp, properties)
+	if err != nil {
+		return response, err
+	}
+	response.ThroughputProperties = properties
+
+	if extraRequestCharge != nil {
+		currentRequestCharge := response.RequestCharge() + *extraRequestCharge
+		response.RawResponse.Header.Set(cosmosHeaderRequestCharge, fmt.Sprint(currentRequestCharge))
+	}
+
+	return response, nil
+}
diff --git a/sdk/data/azcosmos/unique_key_policy.go b/sdk/data/azcosmos/unique_key_policy.go
new file mode 100644
index 0000000000..21d6bdcc52
--- /dev/null
+++ b/sdk/data/azcosmos/unique_key_policy.go
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// UniqueKeyPolicy represents a unique key policy for a container.
+// For more information see https://docs.microsoft.com/azure/cosmos-db/unique-keys
+type UniqueKeyPolicy struct {
+	// Automatic defines if the indexing policy is automatic or manual.
+	UniqueKeys []UniqueKey `json:"uniqueKeys"`
+}
+
+// UniqueKey represents a unique key for a container.
+// For more information see https://docs.microsoft.com/azure/cosmos-db/unique-keys
+type UniqueKey struct {
+	// Paths define a sets of paths which must be unique for each document.
+	Paths []string `json:"paths"`
+}
diff --git a/sdk/data/azcosmos/unixtime.go b/sdk/data/azcosmos/unixtime.go
new file mode 100644
index 0000000000..d0c9a00018
--- /dev/null
+++ b/sdk/data/azcosmos/unixtime.go
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"encoding/json"
+	"strconv"
+	"time"
+)
+
+type UnixTime struct {
+	time.Time
+}
+
+func (u *UnixTime) UnmarshalJSON(b []byte) error {
+	var timestamp int64
+	err := json.Unmarshal(b, &timestamp)
+	if err != nil {
+		return err
+	}
+	u.Time = time.Unix(timestamp, 0)
+	return nil
+}
+
+func (u *UnixTime) MarshalJSON() ([]byte, error) {
+	return []byte(strconv.FormatInt(u.Time.Unix(), 10)), nil
+}
diff --git a/sdk/data/azcosmos/version.go b/sdk/data/azcosmos/version.go
new file mode 100644
index 0000000000..7594aacf28
--- /dev/null
+++ b/sdk/data/azcosmos/version.go
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+// serviceLibVersion is the semantic version (see http://semver.org) of this module.
+const serviceLibVersion = "v0.0.1" //nolint


Test patch:
diff --git a/sdk/azidentity/interactive_browser_credential_test.go b/sdk/azidentity/interactive_browser_credential_test.go
index 1214e3b0ed..f6fa765118 100644
--- a/sdk/azidentity/interactive_browser_credential_test.go
+++ b/sdk/azidentity/interactive_browser_credential_test.go
@@ -78,42 +78,6 @@ func TestInteractiveBrowserCredential_GetTokenSuccess(t *testing.T) {
 	}
 }
 
-func TestInteractiveBrowserCredential_SetPort(t *testing.T) {
-	srv, close := mock.NewTLSServer(mock.WithHTTP2Enabled(true))
-	defer close()
-	tr := &http.Transport{}
-	if err := http2.ConfigureTransport(tr); err != nil {
-		t.Fatalf("Failed to configure http2 transport: %v", err)
-	}
-	tr.TLSClientConfig.InsecureSkipVerify = true
-	client := &http.Client{Transport: tr}
-	srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess)))
-	options := InteractiveBrowserCredentialOptions{}
-	options.AuthorityHost = AuthorityHost(srv.URL())
-	options.HTTPClient = client
-	options.Port = 8080
-	cred, err := NewInteractiveBrowserCredential(&options)
-	if err != nil {
-		t.Fatalf("Unable to create credential. Received: %v", err)
-	}
-	authCodeReceiver = func(ctx context.Context, authorityHost string, opts *InteractiveBrowserCredentialOptions, scopes []string) (*interactiveConfig, error) {
-		if opts.Port != 8080 {
-			t.Fatalf("Did not receive the correct port. Expected: %v, Received: %v", 8080, opts.Port)
-		}
-		return &interactiveConfig{
-			authCode:    "12345",
-			redirectURI: srv.URL(),
-		}, nil
-	}
-	tk, err := cred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{"https://storage.azure.com/.default"}})
-	if err != nil {
-		t.Fatalf("Expected an empty error but received: %v", err)
-	}
-	if tk.Token != "new_token" {
-		t.Fatal("Received unexpected token")
-	}
-}
-
 func TestInteractiveBrowserCredential_GetTokenInvalidCredentials(t *testing.T) {
 	srv, close := mock.NewTLSServer(mock.WithHTTP2Enabled(true))
 	defer close()
@@ -125,7 +89,6 @@ func TestInteractiveBrowserCredential_GetTokenInvalidCredentials(t *testing.T) {
 	client := &http.Client{Transport: tr}
 	srv.SetResponse(mock.WithBody([]byte(accessTokenRespError)), mock.WithStatusCode(http.StatusUnauthorized))
 	options := InteractiveBrowserCredentialOptions{}
-	options.ClientSecret = wrongSecret
 	options.AuthorityHost = AuthorityHost(srv.URL())
 	options.HTTPClient = client
 	cred, err := NewInteractiveBrowserCredential(&options)
diff --git a/sdk/data/azcosmos/async_cache_test.go b/sdk/data/azcosmos/async_cache_test.go
new file mode 100644
index 0000000000..05c9b37836
--- /dev/null
+++ b/sdk/data/azcosmos/async_cache_test.go
@@ -0,0 +1,267 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"errors"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func Test_set(t *testing.T) {
+	key := "someKey"
+	expectedValue := CosmosContainerProperties{Id: "someId"}
+
+	cache := newAsyncCache()
+
+	cache.setValue(key, expectedValue)
+	value, _ := cache.getValue(key)
+	containerProps, _ := value.(CosmosContainerProperties)
+	assert.Equal(t, expectedValue.Id, containerProps.Id)
+}
+
+func Test_setAsync(t *testing.T) {
+	key := "someKeyAsync"
+	expectedValue := CosmosContainerProperties{Id: "someIdAsync"}
+
+	cache := newAsyncCache()
+
+	f := func() *cacheTaskResult {
+
+		return &cacheTaskResult{value: expectedValue, err: nil}
+	}
+
+	_ = cache.set(key, f, context.Background())
+	value, _ := cache.getValue(key)
+	containerProps, _ := value.(CosmosContainerProperties)
+	assert.Equal(t, expectedValue.Id, containerProps.Id)
+}
+
+func Test_getAsync_not_obsolete(t *testing.T) {
+	key := "testAsyncKey"
+	expectedValue0 := CosmosContainerProperties{Id: "0"}
+	expectedValue1 := CosmosContainerProperties{Id: "1"}
+	f1Called := false
+	f2Called := false
+
+	ctx := context.Background()
+
+	cache := newAsyncCache()
+
+	f0 := func() *cacheTaskResult {
+		return &cacheTaskResult{value: expectedValue0, err: nil}
+	}
+
+	_ = cache.set(key, f0, ctx)
+
+	f1 := func() *cacheTaskResult {
+		f1Called = true
+		time.Sleep(3 * time.Second)
+		return &cacheTaskResult{value: expectedValue1, err: nil}
+	}
+
+	_ = cache.getAsync(key, expectedValue0, f1)
+
+	f2 := func() *cacheTaskResult {
+		f2Called = true
+		return &cacheTaskResult{value: expectedValue1, err: nil}
+	}
+
+	_ = cache.getAsync(key, expectedValue0, f2)
+
+	value2, _ := cache.awaitCacheValue(key, ctx)
+	value, _ := cache.awaitCacheValue(key, ctx)
+
+	assert.True(t, f1Called)
+	assert.False(t, f2Called)
+
+	containerProps, _ := value.(CosmosContainerProperties)
+	assert.Equal(t, expectedValue1.Id, containerProps.Id)
+
+	containerProps2, _ := value2.(CosmosContainerProperties)
+	assert.Equal(t, expectedValue1.Id, containerProps2.Id)
+}
+
+func Test_getAsync_obsolete(t *testing.T) {
+	key := "testAsyncObsoleteKey"
+	expectedValue0 := CosmosContainerProperties{Id: "0"}
+	expectedValue1 := CosmosContainerProperties{Id: "1"}
+	expectedValue2 := CosmosContainerProperties{Id: "2"}
+	f1Called := false
+	f2Called := false
+
+	ctx := context.Background()
+
+	cache := newAsyncCache()
+
+	f0 := func() *cacheTaskResult {
+		return &cacheTaskResult{value: expectedValue0, err: nil}
+	}
+
+	_ = cache.set(key, f0, ctx)
+
+	f1 := func() *cacheTaskResult {
+		f1Called = true
+		time.Sleep(3 * time.Second)
+		return &cacheTaskResult{value: expectedValue1, err: nil}
+	}
+
+	_ = cache.getAsync(key, expectedValue0, f1)
+
+	f2 := func() *cacheTaskResult {
+		f2Called = true
+		return &cacheTaskResult{value: expectedValue2, err: nil}
+	}
+
+	_ = cache.getAsync(key, expectedValue1, f2)
+
+	value, _ := cache.awaitCacheValue(key, ctx)
+	containerProps, _ := value.(CosmosContainerProperties)
+
+	value2, _ := cache.awaitCacheValue(key, ctx)
+	containerProps2, _ := value2.(CosmosContainerProperties)
+
+	assert.True(t, f1Called)
+	assert.True(t, f2Called)
+	assert.Equal(t, expectedValue2.Id, containerProps.Id)
+	assert.Equal(t, expectedValue2.Id, containerProps2.Id)
+}
+
+func Test_getAsync_obsolete_with_error(t *testing.T) {
+	key := "testAsyncObsoleteKey"
+	expectedValue0 := CosmosContainerProperties{Id: "0"}
+	expectedValue1 := CosmosContainerProperties{Id: "1"}
+	expectedValue2 := CosmosContainerProperties{Id: "2"}
+	f1Called := false
+	f2Called := false
+
+	ctx := context.Background()
+
+	cache := newAsyncCache()
+
+	f0 := func() *cacheTaskResult {
+		return &cacheTaskResult{value: expectedValue0, err: nil}
+	}
+
+	_ = cache.set(key, f0, ctx)
+
+	f1 := func() *cacheTaskResult {
+		f1Called = true
+		time.Sleep(3 * time.Second)
+		return &cacheTaskResult{value: nil, err: errors.New("some error")}
+	}
+
+	_ = cache.getAsync(key, expectedValue0, f1)
+
+	f2 := func() *cacheTaskResult {
+		f2Called = true
+		return &cacheTaskResult{value: expectedValue2, err: nil}
+	}
+
+	_ = cache.getAsync(key, expectedValue1, f2)
+
+	_, err := cache.awaitCacheValue(key, ctx)
+
+	_, err2 := cache.awaitCacheValue(key, ctx)
+
+	assert.True(t, f1Called)
+	assert.False(t, f2Called)
+	assert.Error(t, err)
+	assert.Error(t, err2)
+}
+
+func Test_getAsync_obsolete_with_context_error(t *testing.T) {
+	key := "testAsyncObsoleteKey"
+	expectedValue0 := CosmosContainerProperties{Id: "0"}
+	expectedValue1 := CosmosContainerProperties{Id: "1"}
+	expectedValue2 := CosmosContainerProperties{Id: "2"}
+	f1Called := false
+	f2Called := false
+
+	ctx := context.Background()
+
+	cache := newAsyncCache()
+
+	f0 := func() *cacheTaskResult {
+		return &cacheTaskResult{value: expectedValue0, err: nil}
+	}
+
+	_ = cache.set(key, f0, ctx)
+
+	f1 := func() *cacheTaskResult {
+		f1Called = true
+		time.Sleep(3 * time.Second)
+		return &cacheTaskResult{value: nil, err: errors.New("some error")}
+	}
+
+	_ = cache.getAsync(key, expectedValue0, f1)
+
+	f2 := func() *cacheTaskResult {
+		f2Called = true
+		return &cacheTaskResult{value: expectedValue2, err: nil}
+	}
+
+	ctx.Done()
+
+	_ = cache.getAsync(key, expectedValue1, f2)
+
+	_, err := cache.awaitCacheValue(key, ctx)
+
+	_, err2 := cache.awaitCacheValue(key, ctx)
+
+	assert.True(t, f1Called)
+	assert.False(t, f2Called)
+	assert.Error(t, err)
+	assert.Error(t, err2)
+}
+
+func Test_remove(t *testing.T) {
+	key := "someKeyToRemove"
+	expectedValue := CosmosContainerProperties{Id: "someIdToRemove"}
+
+	cache := newAsyncCache()
+
+	cache.setValue(key, expectedValue)
+	value, _ := cache.getValue(key)
+	containerProps, _ := value.(CosmosContainerProperties)
+	assert.Equal(t, expectedValue.Id, containerProps.Id)
+
+	cache.remove(key)
+
+	_, ok := cache.getValue(key)
+
+	assert.False(t, ok)
+}
+
+func Test_clear(t *testing.T) {
+	key := "someKeyToClear"
+	expectedValue := CosmosContainerProperties{Id: "someIdToDelete"}
+	key2 := "someKeyToClear2"
+	expectedValue2 := CosmosContainerProperties{Id: "someIdToDelete2"}
+
+	cache := newAsyncCache()
+
+	cache.setValue(key, expectedValue)
+	value, _ := cache.getValue(key)
+	containerProps, _ := value.(CosmosContainerProperties)
+	assert.Equal(t, expectedValue.Id, containerProps.Id)
+
+	cache.setValue(key2, expectedValue2)
+	value2, _ := cache.getValue(key2)
+	containerProps2, _ := value2.(CosmosContainerProperties)
+	assert.Equal(t, expectedValue2.Id, containerProps2.Id)
+
+	cache.clear()
+
+	_, ok := cache.getValue(key)
+
+	assert.False(t, ok)
+
+	_, ok2 := cache.getValue(key2)
+
+	assert.False(t, ok2)
+}
diff --git a/sdk/data/azcosmos/cosmos_client_connection_test.go b/sdk/data/azcosmos/cosmos_client_connection_test.go
new file mode 100644
index 0000000000..c99cf2e6d2
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_client_connection_test.go
@@ -0,0 +1,97 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"testing"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
+)
+
+func TestEnsureErrorIsGeneratedOnResponse(t *testing.T) {
+	someError := &cosmosErrorResponse{
+		Code: "SomeCode",
+	}
+
+	jsonString, err := json.Marshal(someError)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody(jsonString),
+		mock.WithStatusCode(404))
+
+	pl := azruntime.NewPipeline(srv)
+	connection := &cosmosClientConnection{endpoint: srv.URL(), Pipeline: pl}
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: "",
+	}
+	_, err = connection.sendGetRequest("/", context.Background(), operationContext, &CosmosContainerRequestOptions{}, nil)
+	if err == nil {
+		t.Fatal("Expected error")
+	}
+
+	asError := err.(*cosmosError)
+	if asError.ErrorCode() != someError.Code {
+		t.Errorf("Expected %v, but got %v", someError.Code, asError.ErrorCode())
+	}
+
+	if err.Error() != asError.Error() {
+		t.Errorf("Expected %v, but got %v", err.Error(), asError.Error())
+	}
+}
+
+func TestEnsureErrorIsNotGeneratedOnResponse(t *testing.T) {
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithStatusCode(200))
+
+	pl := azruntime.NewPipeline(srv)
+	connection := &cosmosClientConnection{endpoint: srv.URL(), Pipeline: pl}
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: "",
+	}
+	_, err := connection.sendGetRequest("/", context.Background(), operationContext, &CosmosContainerRequestOptions{}, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestRequestEnricherIsCalled(t *testing.T) {
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithStatusCode(200))
+
+	pl := azruntime.NewPipeline(srv)
+	connection := &cosmosClientConnection{endpoint: srv.URL(), Pipeline: pl}
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: "",
+	}
+
+	addHeader := func(r *policy.Request) {
+		r.Raw().Header.Add("my-header", "12345")
+	}
+
+	req, err := connection.createRequest("/", context.Background(), http.MethodGet, operationContext, &CosmosContainerRequestOptions{}, addHeader)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if req.Raw().Header.Get("my-header") != "12345" {
+		t.Errorf("Expected %v, but got %v", "12345", req.Raw().Header.Get("my-header"))
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_client_options_test.go b/sdk/data/azcosmos/cosmos_client_options_test.go
new file mode 100644
index 0000000000..067ac46192
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_client_options_test.go
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"testing"
+)
+
+func TestGetSDKInternalPolicies(t *testing.T) {
+	cosmosClientOptions := &CosmosClientOptions{}
+	policies := cosmosClientOptions.getSDKInternalPolicies()
+	if policies == nil {
+		t.Error("Expected policies to be not nil")
+	}
+
+	if len(policies) == 0 {
+		t.Error("Expected policies to have more than 0 items ")
+	}
+}
+
+func Test_newCosmosClientConnection(t *testing.T) {
+	cred, _ := NewSharedKeyCredential("someKey")
+	connection := newCosmosClientConnection("https://test.com", cred, &CosmosClientOptions{})
+	if connection == nil {
+		t.Error("Expected connection to be not nil")
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_container_properties_test.go b/sdk/data/azcosmos/cosmos_container_properties_test.go
new file mode 100644
index 0000000000..773b708b3e
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_container_properties_test.go
@@ -0,0 +1,174 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"encoding/json"
+	"testing"
+	"time"
+)
+
+func TestContainerPropertiesSerialization(t *testing.T) {
+	nowAsUnix := time.Now().Unix()
+
+	now := UnixTime{
+		Time: time.Unix(nowAsUnix, 0),
+	}
+
+	properties := &CosmosContainerProperties{
+		Id:           "someId",
+		ETag:         "someEtag",
+		SelfLink:     "someSelfLink",
+		ResourceId:   "someResourceId",
+		LastModified: &now,
+		PartitionKeyDefinition: PartitionKeyDefinition{
+			Paths:   []string{"somePath"},
+			Version: PartitionKeyDefinitionVersion2,
+		},
+		IndexingPolicy: &IndexingPolicy{
+			IncludedPaths: []IncludedPath{
+				{Path: "/someIncludedPath"},
+			},
+			ExcludedPaths: []ExcludedPath{
+				{Path: "/someExcludedPath"},
+			},
+			Automatic:    true,
+			IndexingMode: IndexingModeNone,
+			SpatialIndexes: []SpatialIndex{
+				{Path: "/someSpatialIndex",
+					SpatialTypes: []SpatialType{SpatialTypePoint}}},
+			CompositeIndexes: [][]CompositeIndex{
+				{
+					{Path: "/someCompositeIndex",
+						Order: CompositeIndexAscending},
+				}},
+		},
+		UniqueKeyPolicy: &UniqueKeyPolicy{
+			UniqueKeys: []UniqueKey{
+				{Paths: []string{"/someUniqueKey"}},
+			},
+		},
+		ConflictResolutionPolicy: &ConflictResolutionPolicy{
+			Mode:           ConflictResolutionModeLastWriteWins,
+			ResolutionPath: "/someResolutionPath",
+		},
+	}
+
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	otherProperties := &CosmosContainerProperties{}
+	err = json.Unmarshal(jsonString, otherProperties)
+	if err != nil {
+		t.Fatal(err, string(jsonString))
+	}
+
+	if properties.Id != otherProperties.Id {
+		t.Errorf("Expected Id to be %s, but got %s", properties.Id, otherProperties.Id)
+	}
+
+	if properties.ETag != otherProperties.ETag {
+		t.Errorf("Expected ETag to be %s, but got %s", properties.ETag, otherProperties.ETag)
+	}
+
+	if properties.SelfLink != otherProperties.SelfLink {
+		t.Errorf("Expected SelfLink to be %s, but got %s", properties.SelfLink, otherProperties.SelfLink)
+	}
+
+	if properties.ResourceId != otherProperties.ResourceId {
+		t.Errorf("Expected ResourceId to be %s, but got %s", properties.ResourceId, otherProperties.ResourceId)
+	}
+
+	if properties.LastModified.Time != otherProperties.LastModified.Time {
+		t.Errorf("Expected LastModified.Time to be %s, but got %s", properties.LastModified.Time.UTC(), otherProperties.LastModified.Time.UTC())
+	}
+
+	if otherProperties.AnalyticalStoreTimeToLiveInSeconds != nil {
+		t.Errorf("Expected AnalyticalStoreTimeToLiveInSeconds to be nil, but got %d", *otherProperties.AnalyticalStoreTimeToLiveInSeconds)
+	}
+
+	if otherProperties.DefaultTimeToLive != nil {
+		t.Errorf("Expected DefaultTimeToLive to be nil, but got %d", *otherProperties.DefaultTimeToLive)
+	}
+
+	if properties.PartitionKeyDefinition.Paths[0] != otherProperties.PartitionKeyDefinition.Paths[0] {
+		t.Errorf("Expected PartitionKeyDefinition.Paths[0] to be %s, but got %s", properties.PartitionKeyDefinition.Paths[0], otherProperties.PartitionKeyDefinition.Paths[0])
+	}
+
+	if properties.PartitionKeyDefinition.Version != otherProperties.PartitionKeyDefinition.Version {
+		t.Errorf("Expected PartitionKeyDefinition.Version to be %d, but got %d", properties.PartitionKeyDefinition.Version, otherProperties.PartitionKeyDefinition.Version)
+	}
+
+	if otherProperties.IndexingPolicy == nil {
+		t.Errorf("Expected IndexingPolicy to be not nil, but got nil")
+	}
+
+	if otherProperties.IndexingPolicy.Automatic != properties.IndexingPolicy.Automatic {
+		t.Errorf("Expected IndexingPolicy.Automatic to be %t, but got %t", properties.IndexingPolicy.Automatic, otherProperties.IndexingPolicy.Automatic)
+	}
+
+	if otherProperties.IndexingPolicy.IndexingMode != properties.IndexingPolicy.IndexingMode {
+		t.Errorf("Expected IndexingPolicy.IndexingMode to be %v, but got %v", properties.IndexingPolicy.IndexingMode, otherProperties.IndexingPolicy.IndexingMode)
+	}
+
+	if otherProperties.IndexingPolicy.IncludedPaths[0].Path != properties.IndexingPolicy.IncludedPaths[0].Path {
+		t.Errorf("Expected IndexingPolicy.IncludedPaths[0].Path to be %s, but got %s", properties.IndexingPolicy.IncludedPaths[0].Path, otherProperties.IndexingPolicy.IncludedPaths[0].Path)
+	}
+
+	if otherProperties.IndexingPolicy.ExcludedPaths[0].Path != properties.IndexingPolicy.ExcludedPaths[0].Path {
+		t.Errorf("Expected IndexingPolicy.ExcludedPaths[0].Path to be %s, but got %s", properties.IndexingPolicy.ExcludedPaths[0].Path, otherProperties.IndexingPolicy.ExcludedPaths[0].Path)
+	}
+
+	if otherProperties.IndexingPolicy.SpatialIndexes[0].Path != properties.IndexingPolicy.SpatialIndexes[0].Path {
+		t.Errorf("Expected IndexingPolicy.SpatialIndexes[0].Path to be %s, but got %s", properties.IndexingPolicy.SpatialIndexes[0].Path, otherProperties.IndexingPolicy.SpatialIndexes[0].Path)
+	}
+
+	if otherProperties.IndexingPolicy.SpatialIndexes[0].SpatialTypes[0] != properties.IndexingPolicy.SpatialIndexes[0].SpatialTypes[0] {
+		t.Errorf("Expected IndexingPolicy.SpatialIndexes[0].SpatialTypes[0] to be %v, but got %v", properties.IndexingPolicy.SpatialIndexes[0].SpatialTypes[0], otherProperties.IndexingPolicy.SpatialIndexes[0].SpatialTypes[0])
+	}
+
+	if otherProperties.IndexingPolicy.CompositeIndexes[0][0].Path != properties.IndexingPolicy.CompositeIndexes[0][0].Path {
+		t.Errorf("Expected IndexingPolicy.CompositeIndexes[0][0].Path to be %s, but got %s", properties.IndexingPolicy.CompositeIndexes[0][0].Path, otherProperties.IndexingPolicy.CompositeIndexes[0][0].Path)
+	}
+
+	if otherProperties.UniqueKeyPolicy == nil {
+		t.Errorf("Expected UniqueKeyPolicy to be not nil, but got nil")
+	}
+
+	if otherProperties.UniqueKeyPolicy.UniqueKeys[0].Paths[0] != properties.UniqueKeyPolicy.UniqueKeys[0].Paths[0] {
+		t.Errorf("Expected UniqueKeyPolicy.UniqueKeys[0].Paths[0] to be %s, but got %s", properties.UniqueKeyPolicy.UniqueKeys[0].Paths[0], otherProperties.UniqueKeyPolicy.UniqueKeys[0].Paths[0])
+	}
+
+	if otherProperties.ConflictResolutionPolicy == nil {
+		t.Errorf("Expected ConflictResolutionPolicy to be not nil, but got nil")
+	}
+
+	if otherProperties.ConflictResolutionPolicy.Mode != properties.ConflictResolutionPolicy.Mode {
+		t.Errorf("Expected ConflictResolutionPolicy.Mode to be %v, but got %v", properties.ConflictResolutionPolicy.Mode, otherProperties.ConflictResolutionPolicy.Mode)
+	}
+
+	if otherProperties.ConflictResolutionPolicy.ResolutionPath != properties.ConflictResolutionPolicy.ResolutionPath {
+		t.Errorf("Expected ConflictResolutionPolicy.ResolutionPath to be %s, but got %s", properties.ConflictResolutionPolicy.ResolutionPath, otherProperties.ConflictResolutionPolicy.ResolutionPath)
+	}
+}
+
+func TestContainerPropertiesSerializationWithTTL(t *testing.T) {
+	jsonString := []byte(`{"defaultTtl": 10, "analyticalStorageTtl": 20}`)
+
+	properties := &CosmosContainerProperties{}
+	err := json.Unmarshal(jsonString, properties)
+	if err != nil {
+		t.Fatal(err, string(jsonString))
+	}
+
+	if *properties.DefaultTimeToLive != 10 {
+		t.Errorf("Expected properties.DefaultTimeToLive to be %d, but got %d", 10, properties.DefaultTimeToLive)
+	}
+
+	if *properties.AnalyticalStoreTimeToLiveInSeconds != 20 {
+		t.Errorf("Expected properties.AnalyticalStoreTimeToLiveInSeconds to be %d, but got %d", 20, properties.AnalyticalStoreTimeToLiveInSeconds)
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_container_request_options_test.go b/sdk/data/azcosmos/cosmos_container_request_options_test.go
new file mode 100644
index 0000000000..b421b6b7b2
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_container_request_options_test.go
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"testing"
+)
+
+func TestContainerRequestOptionsToHeaders(t *testing.T) {
+	options := &CosmosContainerRequestOptions{}
+	if options.toHeaders() != nil {
+		t.Error("toHeaders should return nil")
+	}
+
+	options.PopulateQuotaInfo = true
+	header := options.toHeaders()
+	if header == nil {
+		t.Error("toHeaders should return non-nil")
+	}
+
+	headers := *header
+	if headers[cosmosHeaderPopulateQuotaInfo] != "true" {
+		t.Errorf("PopulateQuotaInfo not set matching expected %v got %v", true, headers[cosmosHeaderPopulateQuotaInfo])
+	}
+
+	options.PopulateQuotaInfo = false
+	if options.toHeaders() != nil {
+		t.Error("toHeaders should return nil")
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_container_response_test.go b/sdk/data/azcosmos/cosmos_container_response_test.go
new file mode 100644
index 0000000000..8624d0cbfa
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_container_response_test.go
@@ -0,0 +1,116 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"testing"
+	"time"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
+)
+
+func TestContainerResponseParsing(t *testing.T) {
+	nowAsUnix := time.Now().Unix()
+
+	now := UnixTime{
+		Time: time.Unix(nowAsUnix, 0),
+	}
+
+	properties := &CosmosContainerProperties{
+		Id:           "someId",
+		ETag:         "someEtag",
+		SelfLink:     "someSelfLink",
+		ResourceId:   "someResourceId",
+		LastModified: &now,
+		PartitionKeyDefinition: PartitionKeyDefinition{
+			Paths:   []string{"somePath"},
+			Version: PartitionKeyDefinitionVersion2,
+		},
+	}
+
+	container := &CosmosContainer{
+		Id: "someId",
+	}
+
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody(jsonString),
+		mock.WithHeader(cosmosHeaderEtag, "someEtag"),
+		mock.WithHeader(cosmosHeaderActivityId, "someActivityId"),
+		mock.WithHeader(cosmosHeaderRequestCharge, "13.42"))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+	parsedResponse, err := newCosmosContainerResponse(resp, container)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if parsedResponse.RawResponse == nil {
+		t.Fatal("parsedResponse.RawResponse is nil")
+	}
+
+	if parsedResponse.ContainerProperties == nil {
+		t.Fatal("parsedResponse.ContainerProperties is nil")
+	}
+
+	if properties.Id != parsedResponse.ContainerProperties.Id {
+		t.Errorf("Expected Id to be %s, but got %s", properties.Id, parsedResponse.ContainerProperties.Id)
+	}
+
+	if properties.ETag != parsedResponse.ContainerProperties.ETag {
+		t.Errorf("Expected ETag to be %s, but got %s", properties.ETag, parsedResponse.ContainerProperties.ETag)
+	}
+
+	if properties.SelfLink != parsedResponse.ContainerProperties.SelfLink {
+		t.Errorf("Expected SelfLink to be %s, but got %s", properties.SelfLink, parsedResponse.ContainerProperties.SelfLink)
+	}
+
+	if properties.ResourceId != parsedResponse.ContainerProperties.ResourceId {
+		t.Errorf("Expected ResourceId to be %s, but got %s", properties.ResourceId, parsedResponse.ContainerProperties.ResourceId)
+	}
+
+	if properties.LastModified.Time != parsedResponse.ContainerProperties.LastModified.Time {
+		t.Errorf("Expected LastModified.Time to be %s, but got %s", properties.LastModified.Time.UTC(), parsedResponse.ContainerProperties.LastModified.Time.UTC())
+	}
+
+	if properties.PartitionKeyDefinition.Paths[0] != parsedResponse.ContainerProperties.PartitionKeyDefinition.Paths[0] {
+		t.Errorf("Expected PartitionKeyDefinition.Paths[0] to be %s, but got %s", properties.PartitionKeyDefinition.Paths[0], parsedResponse.ContainerProperties.PartitionKeyDefinition.Paths[0])
+	}
+
+	if properties.PartitionKeyDefinition.Version != parsedResponse.ContainerProperties.PartitionKeyDefinition.Version {
+		t.Errorf("Expected PartitionKeyDefinition.Version to be %d, but got %d", properties.PartitionKeyDefinition.Version, parsedResponse.ContainerProperties.PartitionKeyDefinition.Version)
+	}
+
+	if parsedResponse.ActivityId() != "someActivityId" {
+		t.Errorf("Expected ActivityId to be %s, but got %s", "someActivityId", parsedResponse.ActivityId())
+	}
+
+	if parsedResponse.RequestCharge() != 13.42 {
+		t.Errorf("Expected RequestCharge to be %f, but got %f", 13.42, parsedResponse.RequestCharge())
+	}
+
+	if parsedResponse.ETag() != "someEtag" {
+		t.Errorf("Expected ETag to be %s, but got %s", "someEtag", parsedResponse.ActivityId())
+	}
+
+	if parsedResponse.ContainerProperties.Container != container {
+		t.Errorf("Expected Container to be %v, but got %v", container, parsedResponse.ContainerProperties.Container)
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_database_properties_test.go b/sdk/data/azcosmos/cosmos_database_properties_test.go
new file mode 100644
index 0000000000..976d3d7776
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_database_properties_test.go
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"encoding/json"
+	"testing"
+	"time"
+)
+
+func TestDatabasePropertiesSerialization(t *testing.T) {
+	nowAsUnix := time.Now().Unix()
+
+	now := UnixTime{
+		Time: time.Unix(nowAsUnix, 0),
+	}
+
+	properties := &CosmosDatabaseProperties{
+		Id:           "someId",
+		ETag:         "someEtag",
+		SelfLink:     "someSelfLink",
+		ResourceId:   "someResourceId",
+		LastModified: &now,
+	}
+
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	otherProperties := &CosmosDatabaseProperties{}
+	err = json.Unmarshal(jsonString, otherProperties)
+	if err != nil {
+		t.Fatal(err, string(jsonString))
+	}
+
+	if properties.Id != otherProperties.Id {
+		t.Errorf("Expected otherProperties.Id to be %s, but got %s", properties.Id, otherProperties.Id)
+	}
+
+	if properties.ETag != otherProperties.ETag {
+		t.Errorf("Expected otherProperties.ETag to be %s, but got %s", properties.ETag, otherProperties.ETag)
+	}
+
+	if properties.SelfLink != otherProperties.SelfLink {
+		t.Errorf("Expected otherProperties.SelfLink to be %s, but got %s", properties.SelfLink, otherProperties.SelfLink)
+	}
+
+	if properties.ResourceId != otherProperties.ResourceId {
+		t.Errorf("Expected otherProperties.ResourceId to be %s, but got %s", properties.ResourceId, otherProperties.ResourceId)
+	}
+
+	if properties.LastModified.Time != otherProperties.LastModified.Time {
+		t.Errorf("Expected otherProperties.LastModified.Time to be %s, but got %s", properties.LastModified.Time.UTC(), otherProperties.LastModified.Time.UTC())
+	}
+
+}
diff --git a/sdk/data/azcosmos/cosmos_database_request_options_test.go b/sdk/data/azcosmos/cosmos_database_request_options_test.go
new file mode 100644
index 0000000000..799c3dffff
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_database_request_options_test.go
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"testing"
+)
+
+func TestDatabaseRequestOptionsToHeaders(t *testing.T) {
+	options := &CosmosDatabaseRequestOptions{}
+	if options.toHeaders() != nil {
+		t.Error("toHeaders should return nil")
+	}
+
+	options.IfMatchEtag = "etag"
+	options.IfNoneMatchEtag = "noneetag"
+	header := options.toHeaders()
+	if header == nil {
+		t.Error("toHeaders should return non-nil")
+	}
+
+	headers := *header
+	if headers[headerIfMatch] != options.IfMatchEtag {
+		t.Errorf("IfMatchEtag not set matching expected %v got %v", options.IfMatchEtag, headers[headerIfMatch])
+	}
+	if headers[headerIfNoneMatch] != options.IfNoneMatchEtag {
+		t.Errorf("IfNoneMatchEtag not set matching expected %v got %v", options.IfNoneMatchEtag, headers[headerIfNoneMatch])
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_database_response_test.go b/sdk/data/azcosmos/cosmos_database_response_test.go
new file mode 100644
index 0000000000..31b7d1eb30
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_database_response_test.go
@@ -0,0 +1,104 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"testing"
+	"time"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
+)
+
+func TestDatabaseResponseParsing(t *testing.T) {
+	nowAsUnix := time.Now().Unix()
+
+	now := UnixTime{
+		Time: time.Unix(nowAsUnix, 0),
+	}
+
+	properties := &CosmosDatabaseProperties{
+		Id:           "someId",
+		ETag:         "someEtag",
+		SelfLink:     "someSelfLink",
+		ResourceId:   "someResourceId",
+		LastModified: &now,
+	}
+
+	database := &CosmosDatabase{
+		Id: "someId",
+	}
+
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody(jsonString),
+		mock.WithHeader(cosmosHeaderEtag, "someEtag"),
+		mock.WithHeader(cosmosHeaderActivityId, "someActivityId"),
+		mock.WithHeader(cosmosHeaderRequestCharge, "13.42"))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+	parsedResponse, err := newCosmosDatabaseResponse(resp, database)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if parsedResponse.RawResponse == nil {
+		t.Fatal("parsedResponse.RawResponse is nil")
+	}
+
+	if parsedResponse.DatabaseProperties == nil {
+		t.Fatal("parsedResponse.DatabaseProperties is nil")
+	}
+
+	if properties.Id != parsedResponse.DatabaseProperties.Id {
+		t.Errorf("Expected properties.Id to be %s, but got %s", properties.Id, parsedResponse.DatabaseProperties.Id)
+	}
+
+	if properties.ETag != parsedResponse.DatabaseProperties.ETag {
+		t.Errorf("Expected properties.ETag to be %s, but got %s", properties.ETag, parsedResponse.DatabaseProperties.ETag)
+	}
+
+	if properties.SelfLink != parsedResponse.DatabaseProperties.SelfLink {
+		t.Errorf("Expected properties.SelfLink to be %s, but got %s", properties.SelfLink, parsedResponse.DatabaseProperties.SelfLink)
+	}
+
+	if properties.ResourceId != parsedResponse.DatabaseProperties.ResourceId {
+		t.Errorf("Expected properties.ResourceId to be %s, but got %s", properties.ResourceId, parsedResponse.DatabaseProperties.ResourceId)
+	}
+
+	if properties.LastModified.Time != parsedResponse.DatabaseProperties.LastModified.Time {
+		t.Errorf("Expected properties.LastModified.Time to be %s, but got %s", properties.LastModified.Time.UTC(), parsedResponse.DatabaseProperties.LastModified.Time.UTC())
+	}
+
+	if parsedResponse.ActivityId() != "someActivityId" {
+		t.Errorf("Expected ActivityId to be %s, but got %s", "someActivityId", parsedResponse.ActivityId())
+	}
+
+	if parsedResponse.RequestCharge() != 13.42 {
+		t.Errorf("Expected RequestCharge to be %f, but got %f", 13.42, parsedResponse.RequestCharge())
+	}
+
+	if parsedResponse.ETag() != "someEtag" {
+		t.Errorf("Expected ETag to be %s, but got %s", "someEtag", parsedResponse.ActivityId())
+	}
+
+	if parsedResponse.DatabaseProperties.Database != database {
+		t.Errorf("Expected database to be %v, but got %v", database, parsedResponse.DatabaseProperties.Database)
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_error_test.go b/sdk/data/azcosmos/cosmos_error_test.go
new file mode 100644
index 0000000000..db0d40642b
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_error_test.go
@@ -0,0 +1,94 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"testing"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
+)
+
+func TestCosmosErrorOnEmptyResponse(t *testing.T) {
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithStatusCode(404))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+
+	cError := newCosmosError(resp)
+	if cError.Error() != "response contained no body" {
+		t.Errorf("Expected response contained no body, but got %v", cError)
+	}
+}
+
+func TestCosmosErrorOnNonJsonBody(t *testing.T) {
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody([]byte("This is not JSON")),
+		mock.WithStatusCode(404))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+
+	cError := newCosmosError(resp)
+	if cError.Error() != "This is not JSON" {
+		t.Errorf("Expected This is not JSON, but got %v", cError)
+	}
+}
+
+func TestCosmosErrorOnJsonBody(t *testing.T) {
+	someError := &cosmosErrorResponse{
+		Code: "SomeCode",
+	}
+
+	jsonString, err := json.Marshal(someError)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody(jsonString),
+		mock.WithStatusCode(404))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+
+	cError := newCosmosError(resp)
+	asError := cError.(*cosmosError)
+	if asError.ErrorCode() != someError.Code {
+		t.Errorf("Expected %v, but got %v", someError.Code, asError.ErrorCode())
+	}
+
+	if asError.StatusCode() != 404 {
+		t.Errorf("Expected 404 Not Found, but got %v", asError.StatusCode())
+	}
+
+	if asError.Error() != string(jsonString) {
+		t.Errorf("Expected %v, but got %v", string(jsonString), asError.Error())
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_item_request_options_test.go b/sdk/data/azcosmos/cosmos_item_request_options_test.go
new file mode 100644
index 0000000000..6e491cccdc
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_item_request_options_test.go
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"testing"
+)
+
+func TestItemRequestOptionsToHeaders(t *testing.T) {
+	options := &CosmosItemRequestOptions{}
+	options.PreTriggers = []string{"preTrigger1", "preTrigger2"}
+	options.PostTriggers = []string{"postTrigger1", "postTrigger2"}
+	options.ConsistencyLevel = ConsistencyLevelSession.ToPtr()
+	options.SessionToken = "sessionToken"
+	options.IndexingDirective = IndexingDirectiveInclude.ToPtr()
+	header := options.toHeaders()
+	if header == nil {
+		t.Error("toHeaders should return non-nil")
+	}
+
+	headers := *header
+	if headers[cosmosHeaderPreTriggerInclude] != "preTrigger1,preTrigger2" {
+		t.Errorf("PreTriggerInclude should be preTrigger1,preTrigger2 but got %v", headers[cosmosHeaderPreTriggerInclude])
+	}
+	if headers[cosmosHeaderPostTriggerInclude] != "postTrigger1,postTrigger2" {
+		t.Errorf("PostTriggerInclude should be postTrigger1,postTrigger2 but got %v", headers[cosmosHeaderPostTriggerInclude])
+	}
+	if headers[cosmosHeaderConsistencyLevel] != "Session" {
+		t.Errorf("ConsistencyLevel should be Session but got %v", headers[cosmosHeaderConsistencyLevel])
+	}
+	if headers[cosmosHeaderIndexingDirective] != "Include" {
+		t.Errorf("IndexingDirective should be Include but got %v", headers[cosmosHeaderIndexingDirective])
+	}
+	if headers[cosmosHeaderSessionToken] != "sessionToken" {
+		t.Errorf("SessionToken should be sessionToken but got %v", headers[cosmosHeaderSessionToken])
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_item_response_test.go b/sdk/data/azcosmos/cosmos_item_response_test.go
new file mode 100644
index 0000000000..d4cbd9e07e
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_item_response_test.go
@@ -0,0 +1,66 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"testing"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
+)
+
+func TestItemResponseParsing(t *testing.T) {
+	properties := map[string]string{
+		"id":   "id",
+		"name": "name",
+	}
+
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody(jsonString),
+		mock.WithHeader(cosmosHeaderEtag, "someEtag"),
+		mock.WithHeader(cosmosHeaderActivityId, "someActivityId"),
+		mock.WithHeader(cosmosHeaderRequestCharge, "13.42"))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+	parsedResponse, err := newCosmosItemResponse(resp)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if parsedResponse.RawResponse == nil {
+		t.Fatal("parsedResponse.RawResponse is nil")
+	}
+
+	if parsedResponse.ActivityId() != "someActivityId" {
+		t.Errorf("Expected ActivityId to be %s, but got %s", "someActivityId", parsedResponse.ActivityId())
+	}
+
+	if parsedResponse.RequestCharge() != 13.42 {
+		t.Errorf("Expected RequestCharge to be %f, but got %f", 13.42, parsedResponse.RequestCharge())
+	}
+
+	if parsedResponse.ETag() != "someEtag" {
+		t.Errorf("Expected ETag to be %s, but got %s", "someEtag", parsedResponse.ActivityId())
+	}
+
+	if string(parsedResponse.Value) != string(jsonString) {
+		t.Errorf("Expected Value to be %s, but got %s", string(jsonString), string(parsedResponse.Value))
+	}
+}
diff --git a/sdk/data/azcosmos/cosmos_paths_test.go b/sdk/data/azcosmos/cosmos_paths_test.go
new file mode 100644
index 0000000000..cc4ff6e202
--- /dev/null
+++ b/sdk/data/azcosmos/cosmos_paths_test.go
@@ -0,0 +1,57 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"testing"
+)
+
+func TestPathCreateLink(t *testing.T) {
+
+	expected := "dbs/testdb/colls/testcoll"
+	actual := createLink("dbs/testdb", pathSegmentCollection, "testcoll")
+	if actual != expected {
+		t.Errorf("Expected %s, got %s", expected, actual)
+	}
+
+	expected = "dbs/testdb"
+	actual = createLink("", pathSegmentDatabase, "testdb")
+	if actual != expected {
+		t.Errorf("Expected %s, got %s", expected, actual)
+	}
+
+	expected = "dbs/esc%40ped"
+	actual = createLink("", pathSegmentDatabase, "esc@ped")
+	if actual != expected {
+		t.Errorf("Expected %s, got %s", expected, actual)
+	}
+}
+
+func TestPathToResourceTypeMapping(t *testing.T) {
+	verifyPathResultAndExpectation(t, resourceTypeDatabase, pathSegmentDatabase)
+	verifyPathResultAndExpectation(t, resourceTypeCollection, pathSegmentCollection)
+	verifyPathResultAndExpectation(t, resourceTypeDocument, pathSegmentDocument)
+	verifyPathResultAndExpectation(t, resourceTypeDatabaseAccount, pathSegmentDatabaseAccount)
+	verifyPathResultAndExpectation(t, resourceTypeOffer, pathSegmentOffer)
+	verifyPathResultAndExpectation(t, resourceTypeUser, pathSegmentUser)
+	verifyPathResultAndExpectation(t, resourceTypeStoredProcedure, pathSegmentStoredProcedure)
+	verifyPathResultAndExpectation(t, resourceTypeUserDefinedFunction, pathSegmentUserDefinedFunction)
+	verifyPathResultAndExpectation(t, resourceTypeTrigger, pathSegmentTrigger)
+	verifyPathResultAndExpectation(t, resourceTypePermission, pathSegmentPermission)
+	verifyPathResultAndExpectation(t, resourceTypePartitionKeyRange, pathSegmentPartitionKeyRange)
+	verifyPathResultAndExpectation(t, resourceTypeClientEncryptionKey, pathSegmentClientEncryptionKey)
+	verifyPathResultAndExpectation(t, resourceTypeUser, pathSegmentUser)
+	verifyPathResultAndExpectation(t, resourceTypeConflict, pathSegmentConflict)
+}
+
+func verifyPathResultAndExpectation(t *testing.T, resourceType resourceType, expected string) {
+	actual, err := getResourcePath(resourceType)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if actual != expected {
+		t.Errorf("Expected %s, got %s", expected, actual)
+	}
+}
diff --git a/sdk/data/azcosmos/emulator_cosmos_container_test.go b/sdk/data/azcosmos/emulator_cosmos_container_test.go
new file mode 100644
index 0000000000..aaa6722a70
--- /dev/null
+++ b/sdk/data/azcosmos/emulator_cosmos_container_test.go
@@ -0,0 +1,167 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"testing"
+)
+
+func TestContainerCRUD(t *testing.T) {
+	emulatorTests := newEmulatorTests(t)
+	client := emulatorTests.getClient(t)
+
+	database := emulatorTests.createDatabase(t, context.TODO(), client, "containerCRUD")
+	defer emulatorTests.deleteDatabase(t, context.TODO(), database)
+	properties := CosmosContainerProperties{
+		Id: "aContainer",
+		PartitionKeyDefinition: PartitionKeyDefinition{
+			Paths: []string{"/id"},
+		},
+		IndexingPolicy: &IndexingPolicy{
+			IncludedPaths: []IncludedPath{
+				{Path: "/*"},
+			},
+			ExcludedPaths: []ExcludedPath{
+				{Path: "/\"_etag\"/?"},
+			},
+			Automatic:    true,
+			IndexingMode: IndexingModeConsistent,
+		},
+	}
+
+	throughput := NewManualThroughputProperties(400)
+
+	resp, err := database.CreateContainer(context.TODO(), properties, throughput, nil)
+	if err != nil {
+		t.Fatalf("Failed to create container: %v", err)
+	}
+
+	if resp.ContainerProperties.Id != properties.Id {
+		t.Errorf("Unexpected id match: %v", resp.ContainerProperties)
+	}
+
+	if resp.ContainerProperties.PartitionKeyDefinition.Paths[0] != properties.PartitionKeyDefinition.Paths[0] {
+		t.Errorf("Unexpected path match: %v", resp.ContainerProperties)
+	}
+
+	container := resp.ContainerProperties.Container
+	resp, err = container.Read(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to read container: %v", err)
+	}
+
+	updatedProperties := CosmosContainerProperties{
+		Id: "aContainer",
+		PartitionKeyDefinition: PartitionKeyDefinition{
+			Paths: []string{"/id"},
+		},
+		IndexingPolicy: &IndexingPolicy{
+			IncludedPaths: []IncludedPath{},
+			ExcludedPaths: []ExcludedPath{},
+			Automatic:     false,
+			IndexingMode:  IndexingModeNone,
+		},
+	}
+
+	resp, err = container.Replace(context.TODO(), updatedProperties, nil)
+	if err != nil {
+		t.Fatalf("Failed to update container: %v", err)
+	}
+
+	throughputResponse, err := container.ReadThroughput(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to read throughput: %v", err)
+	}
+
+	mt, err := throughputResponse.ThroughputProperties.ManualThroughput()
+	if err != nil {
+		t.Errorf("Failed to read throughput: %v", err)
+	}
+
+	if mt != 400 {
+		t.Errorf("Unexpected throughput: %v", mt)
+	}
+
+	newScale := NewManualThroughputProperties(500)
+	_, err = container.ReplaceThroughput(context.TODO(), *newScale, nil)
+	if err != nil {
+		t.Errorf("Failed to read throughput: %v", err)
+	}
+
+	resp, err = container.Delete(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to delete container: %v", err)
+	}
+}
+
+func TestContainerAutoscaleCRUD(t *testing.T) {
+	emulatorTests := newEmulatorTests(t)
+	client := emulatorTests.getClient(t)
+
+	database := emulatorTests.createDatabase(t, context.TODO(), client, "containerCRUD")
+	defer emulatorTests.deleteDatabase(t, context.TODO(), database)
+	properties := CosmosContainerProperties{
+		Id: "aContainer",
+		PartitionKeyDefinition: PartitionKeyDefinition{
+			Paths: []string{"/id"},
+		},
+		IndexingPolicy: &IndexingPolicy{
+			IncludedPaths: []IncludedPath{
+				{Path: "/*"},
+			},
+			ExcludedPaths: []ExcludedPath{
+				{Path: "/\"_etag\"/?"},
+			},
+			Automatic:    true,
+			IndexingMode: IndexingModeConsistent,
+		},
+	}
+
+	throughput := NewAutoscaleThroughputProperties(5000)
+
+	resp, err := database.CreateContainer(context.TODO(), properties, throughput, nil)
+	if err != nil {
+		t.Fatalf("Failed to create container: %v", err)
+	}
+
+	if resp.ContainerProperties.Id != properties.Id {
+		t.Errorf("Unexpected id match: %v", resp.ContainerProperties)
+	}
+
+	if resp.ContainerProperties.PartitionKeyDefinition.Paths[0] != properties.PartitionKeyDefinition.Paths[0] {
+		t.Errorf("Unexpected path match: %v", resp.ContainerProperties)
+	}
+
+	container := resp.ContainerProperties.Container
+	resp, err = container.Read(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to read container: %v", err)
+	}
+
+	throughputResponse, err := container.ReadThroughput(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to read throughput: %v", err)
+	}
+
+	maxru, err := throughputResponse.ThroughputProperties.AutoscaleMaxThroughput()
+	if err != nil {
+		t.Errorf("Failed to read throughput: %v", err)
+	}
+
+	if maxru != 5000 {
+		t.Errorf("Unexpected throughput: %v", maxru)
+	}
+
+	newScale := NewAutoscaleThroughputProperties(10000)
+	_, err = container.ReplaceThroughput(context.TODO(), *newScale, nil)
+	if err != nil {
+		t.Errorf("Failed to read throughput: %v", err)
+	}
+
+	resp, err = container.Delete(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to delete container: %v", err)
+	}
+}
diff --git a/sdk/data/azcosmos/emulator_cosmos_database_test.go b/sdk/data/azcosmos/emulator_cosmos_database_test.go
new file mode 100644
index 0000000000..05c0a8b52e
--- /dev/null
+++ b/sdk/data/azcosmos/emulator_cosmos_database_test.go
@@ -0,0 +1,94 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"testing"
+)
+
+func TestDatabaseCRUD(t *testing.T) {
+	emulatorTests := newEmulatorTests(t)
+	client := emulatorTests.getClient(t)
+
+	database := CosmosDatabaseProperties{Id: "baseDbTest"}
+
+	resp, err := client.CreateDatabase(context.TODO(), database, nil, nil)
+	if err != nil {
+		t.Fatalf("Failed to create database: %v", err)
+	}
+
+	if resp.DatabaseProperties.Id != database.Id {
+		t.Errorf("Unexpected id match: %v", resp.DatabaseProperties)
+	}
+
+	resp, err = resp.DatabaseProperties.Database.Read(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to read database: %v", err)
+	}
+
+	if resp.DatabaseProperties.Id != database.Id {
+		t.Errorf("Unexpected id match: %v", resp.DatabaseProperties)
+	}
+
+	throughputResponse, err := resp.DatabaseProperties.Database.ReadThroughput(context.TODO(), nil)
+	if err == nil {
+		t.Fatalf("Expected not finding throughput but instead got : %v", throughputResponse)
+	}
+
+	resp, err = resp.DatabaseProperties.Database.Delete(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to delete database: %v", err)
+	}
+}
+
+func TestDatabaseWithOfferCRUD(t *testing.T) {
+	emulatorTests := newEmulatorTests(t)
+	client := emulatorTests.getClient(t)
+
+	database := CosmosDatabaseProperties{Id: "baseDbTest"}
+	tp := NewManualThroughputProperties(400)
+	resp, err := client.CreateDatabase(context.TODO(), database, tp, nil)
+	if err != nil {
+		t.Fatalf("Failed to create database: %v", err)
+	}
+
+	if resp.DatabaseProperties.Id != database.Id {
+		t.Errorf("Unexpected id match: %v", resp.DatabaseProperties)
+	}
+
+	resp, err = resp.DatabaseProperties.Database.Read(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to read database: %v", err)
+	}
+
+	if resp.DatabaseProperties.Id != database.Id {
+		t.Errorf("Unexpected id match: %v", resp.DatabaseProperties)
+	}
+
+	throughputResponse, err := resp.DatabaseProperties.Database.ReadThroughput(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to read throughput: %v", err)
+	}
+
+	mt, err := throughputResponse.ThroughputProperties.ManualThroughput()
+	if err != nil {
+		t.Errorf("Failed to read throughput: %v", err)
+	}
+
+	if mt != 400 {
+		t.Errorf("Unexpected throughput: %v", mt)
+	}
+
+	newScale := NewManualThroughputProperties(500)
+	_, err = resp.DatabaseProperties.Database.ReplaceThroughput(context.TODO(), *newScale, nil)
+	if err != nil {
+		t.Errorf("Failed to read throughput: %v", err)
+	}
+
+	resp, err = resp.DatabaseProperties.Database.Delete(context.TODO(), nil)
+	if err != nil {
+		t.Fatalf("Failed to delete database: %v", err)
+	}
+}
diff --git a/sdk/data/azcosmos/emulator_cosmos_item_test.go b/sdk/data/azcosmos/emulator_cosmos_item_test.go
new file mode 100644
index 0000000000..43b00609c5
--- /dev/null
+++ b/sdk/data/azcosmos/emulator_cosmos_item_test.go
@@ -0,0 +1,124 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"encoding/json"
+	"testing"
+)
+
+func TestItemCRUD(t *testing.T) {
+	emulatorTests := newEmulatorTests(t)
+	client := emulatorTests.getClient(t)
+
+	database := emulatorTests.createDatabase(t, context.TODO(), client, "itemCRUD")
+	defer emulatorTests.deleteDatabase(t, context.TODO(), database)
+	properties := CosmosContainerProperties{
+		Id: "aContainer",
+		PartitionKeyDefinition: PartitionKeyDefinition{
+			Paths: []string{"/id"},
+		},
+	}
+
+	resp, err := database.CreateContainer(context.TODO(), properties, nil, nil)
+	if err != nil {
+		t.Fatalf("Failed to create container: %v", err)
+	}
+
+	item := map[string]string{
+		"id":    "1",
+		"value": "2",
+	}
+
+	container := resp.ContainerProperties.Container
+	pk, err := NewPartitionKey("1")
+	if err != nil {
+		t.Fatalf("Failed to create pk: %v", err)
+	}
+
+	itemResponse, err := container.CreateItem(context.TODO(), pk, item, nil)
+	if err != nil {
+		t.Fatalf("Failed to create item: %v", err)
+	}
+
+	// No content on write by default
+	if len(itemResponse.Value) != 0 {
+		t.Fatalf("Expected empty response, got %v", itemResponse.Value)
+	}
+
+	itemResponse, err = container.ReadItem(context.TODO(), pk, "1", nil)
+	if err != nil {
+		t.Fatalf("Failed to read item: %v", err)
+	}
+
+	if len(itemResponse.Value) == 0 {
+		t.Fatalf("Expected non-empty response, got %v", itemResponse.Value)
+	}
+
+	var itemResponseBody map[string]interface{}
+	err = json.Unmarshal(itemResponse.Value, &itemResponseBody)
+	if err != nil {
+		t.Fatalf("Failed to unmarshal item response: %v", err)
+	}
+	if itemResponseBody["id"] != "1" {
+		t.Fatalf("Expected id to be 1, got %v", itemResponseBody["id"])
+	}
+	if itemResponseBody["value"] != "2" {
+		t.Fatalf("Expected value to be 2, got %v", itemResponseBody["value"])
+	}
+
+	item["value"] = "3"
+	itemResponse, err = container.ReplaceItem(context.TODO(), pk, "1", item, &CosmosItemRequestOptions{EnableContentResponseOnWrite: true})
+	if err != nil {
+		t.Fatalf("Failed to replace item: %v", err)
+	}
+
+	// Explicitly requesting body on write
+	if len(itemResponse.Value) == 0 {
+		t.Fatalf("Expected non-empty response, got %v", itemResponse.Value)
+	}
+
+	err = json.Unmarshal(itemResponse.Value, &itemResponseBody)
+	if err != nil {
+		t.Fatalf("Failed to unmarshal item response: %v", err)
+	}
+	if itemResponseBody["id"] != "1" {
+		t.Fatalf("Expected id to be 1, got %v", itemResponseBody["id"])
+	}
+	if itemResponseBody["value"] != "3" {
+		t.Fatalf("Expected value to be 3, got %v", itemResponseBody["value"])
+	}
+
+	item["value"] = "4"
+	itemResponse, err = container.UpsertItem(context.TODO(), pk, item, &CosmosItemRequestOptions{EnableContentResponseOnWrite: true})
+	if err != nil {
+		t.Fatalf("Failed to upsert item: %v", err)
+	}
+
+	// Explicitly requesting body on write
+	if len(itemResponse.Value) == 0 {
+		t.Fatalf("Expected non-empty response, got %v", itemResponse.Value)
+	}
+
+	err = json.Unmarshal(itemResponse.Value, &itemResponseBody)
+	if err != nil {
+		t.Fatalf("Failed to unmarshal item response: %v", err)
+	}
+	if itemResponseBody["id"] != "1" {
+		t.Fatalf("Expected id to be 1, got %v", itemResponseBody["id"])
+	}
+	if itemResponseBody["value"] != "4" {
+		t.Fatalf("Expected value to be 4, got %v", itemResponseBody["value"])
+	}
+
+	itemResponse, err = container.DeleteItem(context.TODO(), pk, "1", nil)
+	if err != nil {
+		t.Fatalf("Failed to replace item: %v", err)
+	}
+
+	if len(itemResponse.Value) != 0 {
+		t.Fatalf("Expected empty response, got %v", itemResponse.Value)
+	}
+}
diff --git a/sdk/data/azcosmos/emulator_tests.go b/sdk/data/azcosmos/emulator_tests.go
new file mode 100644
index 0000000000..7c89203962
--- /dev/null
+++ b/sdk/data/azcosmos/emulator_tests.go
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"os"
+	"testing"
+)
+
+type emulatorTests struct {
+	host string
+	key  string
+}
+
+func newEmulatorTests(t *testing.T) *emulatorTests {
+	envCheck := os.Getenv("EMULATOR")
+	if envCheck == "" {
+		t.Skip("set EMULATOR environment variable to run this test")
+	}
+
+	return &emulatorTests{
+		host: "https://localhost:8081/",
+		key:  "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
+	}
+}
+
+func (e *emulatorTests) getClient(t *testing.T) *CosmosClient {
+	cred, _ := NewSharedKeyCredential(e.key)
+	client, err := NewCosmosClient(e.host, cred, nil)
+	if err != nil {
+		t.Fatalf("Failed to create client: %v", err)
+	}
+
+	return client
+}
+
+func (e *emulatorTests) createDatabase(
+	t *testing.T,
+	ctx context.Context,
+	client *CosmosClient,
+	dbName string) *CosmosDatabase {
+	database := CosmosDatabaseProperties{Id: dbName}
+	resp, err := client.CreateDatabase(ctx, database, nil, nil)
+	if err != nil {
+		t.Fatalf("Failed to create database: %v", err)
+	}
+
+	if resp.DatabaseProperties.Id != database.Id {
+		t.Errorf("Unexpected id match: %v", resp.DatabaseProperties)
+	}
+
+	return resp.DatabaseProperties.Database
+}
+
+func (e *emulatorTests) deleteDatabase(
+	t *testing.T,
+	ctx context.Context,
+	database *CosmosDatabase) {
+	_, err := database.Delete(ctx, nil)
+	if err != nil {
+		t.Fatalf("Failed to delete database: %v", err)
+	}
+}
diff --git a/sdk/data/azcosmos/partition_key_test.go b/sdk/data/azcosmos/partition_key_test.go
new file mode 100644
index 0000000000..d9b1545d22
--- /dev/null
+++ b/sdk/data/azcosmos/partition_key_test.go
@@ -0,0 +1,131 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestInvalidPartitionKeyValues(t *testing.T) {
+	invalidTypes := []interface{}{
+		complex64(0),
+		complex128(0),
+		[]byte(nil),
+		[]byte{},
+		// whatever other type of struct
+		cosmosOperationContext{},
+	}
+
+	for _, invalidType := range invalidTypes {
+		_, err := NewPartitionKey(invalidType)
+		if err == nil {
+			t.Errorf("Expected error for partition key type %v", invalidType)
+		}
+	}
+}
+
+func TestValidPartitionKeyValues(t *testing.T) {
+	validTypes := map[interface{}]string{
+		nil:           "[null]",
+		true:          "[true]",
+		false:         "[false]",
+		"some string": "[\"some string\"]",
+		int(10):       "[10]",
+		int8(10):      "[10]",
+		int16(10):     "[10]",
+		int32(10):     "[10]",
+		int64(10):     "[10]",
+		uint(10):      "[10]",
+		uint8(10):     "[10]",
+		uint16(10):    "[10]",
+		uint32(10):    "[10]",
+		uint64(10):    "[10]",
+		float32(10.5): "[10.5]",
+		float64(10.5): "[10.5]",
+	}
+
+	for validType, expectedSerialization := range validTypes {
+		pk, err := NewPartitionKey(validType)
+		if err != nil {
+			t.Errorf("Expected success for partition key type %v and got %v", validType, err)
+		}
+
+		if len(pk.partitionKeyInternal.components) != 1 {
+			t.Errorf("Expected partition key to have 1 component, but it has %v", len(pk.partitionKeyInternal.components))
+		}
+
+		serialization, err := pk.toJsonString()
+		if err != nil {
+			t.Errorf("Failed to serialize PK for %v, got %v", validType, err)
+		}
+
+		if serialization != expectedSerialization {
+			t.Errorf("Expected serialization %v, but got %v", expectedSerialization, serialization)
+		}
+	}
+}
+
+func TestPartitionKeyEmpty(t *testing.T) {
+	pk := &PartitionKey{
+		partitionKeyInternal: emptyPartitionKey,
+	}
+
+	serialization, err := pk.toJsonString()
+	if err != nil {
+		t.Errorf("Failed to serialize PK, %v", err)
+	}
+
+	if serialization != "[]" {
+		t.Errorf("Expected serialization [], but got %v", serialization)
+	}
+}
+
+func TestPartitionKeyUndefined(t *testing.T) {
+	pk := &PartitionKey{
+		partitionKeyInternal: undefinedPartitionKey,
+	}
+
+	serialization, err := pk.toJsonString()
+	if err != nil {
+		t.Errorf("Failed to serialize PK, %v", err)
+	}
+
+	if serialization != "[{}]" {
+		t.Errorf("Expected serialization [{}], but got %v", serialization)
+	}
+}
+
+func TestPartitionKeyEquality(t *testing.T) {
+	validTypes := []interface{}{
+		nil,
+		true,
+		false,
+		"some string",
+		int(10),
+		int8(10),
+		int16(10),
+		int32(10),
+		int64(10),
+		uint(10),
+		uint8(10),
+		uint16(10),
+		uint32(10),
+		uint64(10),
+		float32(10.5),
+		float64(10.5),
+	}
+
+	for _, validType := range validTypes {
+		pk, err := NewPartitionKey(validType)
+		if err != nil {
+			t.Errorf("Expected success for partition key type %v and got %v", validType, err)
+		}
+
+		pk2, _ := NewPartitionKey(validType)
+		if !reflect.DeepEqual(pk, pk2) {
+			t.Errorf("Expected %v to equal %v", pk, pk2)
+		}
+	}
+}
diff --git a/sdk/data/azcosmos/resource_throttle_retry_policy_test.go b/sdk/data/azcosmos/resource_throttle_retry_policy_test.go
new file mode 100644
index 0000000000..b796046ccc
--- /dev/null
+++ b/sdk/data/azcosmos/resource_throttle_retry_policy_test.go
@@ -0,0 +1,103 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"net/http"
+	"testing"
+	"time"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
+)
+
+func TestDefaultRetryConfiguration(t *testing.T) {
+	cosmosClientOptions := &CosmosClientOptions{}
+	retryPolicy := newResourceThrottleRetryPolicy(cosmosClientOptions)
+	if retryPolicy.MaxRetryCount != defaultResourceThrottleRetryPolicyRetryCount {
+		t.Errorf("Expected the MaxRetryCount to match the default but got, but got %d", retryPolicy.MaxRetryCount)
+	}
+
+	if retryPolicy.MaxWaitTime != defaultResourceThrottleRetryPolicyMaxWaitTime {
+		t.Errorf("Expected the MaxWaitTime to match the default but got, but got %s", retryPolicy.MaxWaitTime)
+	}
+}
+
+func TestCustomRetryConfiguration(t *testing.T) {
+	cosmosClientOptions := &CosmosClientOptions{}
+	maxRetryCount := 5
+	maxRetryDuration, _ := time.ParseDuration("1s")
+	cosmosClientOptions.RateLimitedRetry = &CosmosClientOptionsRateLimitedRetry{
+		MaxRetryAttempts: maxRetryCount,
+		MaxRetryWaitTime: maxRetryDuration,
+	}
+	retryPolicy := newResourceThrottleRetryPolicy(cosmosClientOptions)
+	if retryPolicy.MaxRetryCount != maxRetryCount {
+		t.Errorf("Expected the MaxRetryCount to match the %d but got, but got %d", maxRetryCount, retryPolicy.MaxRetryCount)
+	}
+
+	if retryPolicy.MaxWaitTime != maxRetryDuration {
+		t.Errorf("Expected the MaxWaitTime to match the %s but got, but got %s", maxRetryDuration, retryPolicy.MaxWaitTime)
+	}
+}
+
+func TestRetryOn429WithCustomCount(t *testing.T) {
+	cosmosClientOptions := &CosmosClientOptions{}
+	maxRetryCount := 5
+	maxRetryDuration, _ := time.ParseDuration("5s")
+	cosmosClientOptions.RateLimitedRetry = &CosmosClientOptionsRateLimitedRetry{
+		MaxRetryAttempts: maxRetryCount,
+		MaxRetryWaitTime: maxRetryDuration,
+	}
+	retryPolicy := newResourceThrottleRetryPolicy(cosmosClientOptions)
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(mock.WithStatusCode(http.StatusTooManyRequests))
+
+	pl := azruntime.NewPipeline(srv, retryPolicy)
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatalf("unexpected error: %v", err)
+	}
+
+	resp, _ := pl.Do(req)
+	if resp.StatusCode != http.StatusTooManyRequests {
+		t.Fatalf("unexpected status code: %d", resp.StatusCode)
+	}
+	if r := srv.Requests(); r != maxRetryCount {
+		t.Fatalf("wrong request count, got %d expected %d", r, maxRetryCount)
+	}
+}
+
+func TestRetryOn429WithCustomTime(t *testing.T) {
+	cosmosClientOptions := &CosmosClientOptions{}
+	maxRetryCount := 5
+	maxRetryDuration, _ := time.ParseDuration("1s")
+	cosmosClientOptions.RateLimitedRetry = &CosmosClientOptionsRateLimitedRetry{
+		MaxRetryAttempts: maxRetryCount,
+		MaxRetryWaitTime: maxRetryDuration,
+	}
+	retryPolicy := newResourceThrottleRetryPolicy(cosmosClientOptions)
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	// Should wait only 1 second and when the retry comes, it should stop
+	srv.SetResponse(mock.WithStatusCode(http.StatusTooManyRequests), mock.WithHeader(cosmosHeaderRetryAfter, "1000"))
+
+	pl := azruntime.NewPipeline(srv, retryPolicy)
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatalf("unexpected error: %v", err)
+	}
+
+	resp, _ := pl.Do(req)
+	if resp.StatusCode != http.StatusTooManyRequests {
+		t.Fatalf("unexpected status code: %d", resp.StatusCode)
+	}
+	if r := srv.Requests(); r != 2 {
+		t.Fatalf("wrong request count, got %d expected %d", r, 2)
+	}
+}
diff --git a/sdk/data/azcosmos/shared_key_credential_test.go b/sdk/data/azcosmos/shared_key_credential_test.go
new file mode 100644
index 0000000000..3ebeeb687d
--- /dev/null
+++ b/sdk/data/azcosmos/shared_key_credential_test.go
@@ -0,0 +1,110 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"net/url"
+	"strings"
+	"testing"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/stretchr/testify/assert"
+)
+
+func Test_buildCanonicalizedAuthHeader(t *testing.T) {
+	key := "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
+
+	cred, err := NewSharedKeyCredential(key)
+
+	assert.NoError(t, err)
+
+	method := "GET"
+	resourceType := "dbs"
+	resourceId := "dbs/testdb"
+	xmsDate := "Thu, 27 Apr 2017 00:51:12 GMT"
+	tokenType := "master"
+	version := "1.0"
+
+	emptyAuthHeader := cred.buildCanonicalizedAuthHeader("", resourceType, resourceId, xmsDate, tokenType, version)
+	assert.Equal(t, emptyAuthHeader, "")
+	emptyAuthHeader = cred.buildCanonicalizedAuthHeader(method, "", resourceId, xmsDate, tokenType, version)
+	assert.Equal(t, emptyAuthHeader, "")
+
+	stringToSign := join(strings.ToLower(method), "\n", strings.ToLower(resourceType), "\n", resourceId, "\n", strings.ToLower(xmsDate), "\n", "", "\n")
+	signature := cred.computeHMACSHA256(stringToSign)
+	expected := url.QueryEscape(fmt.Sprintf("type=%s&ver=%s&sig=%s", tokenType, version, signature))
+
+	authHeader := cred.buildCanonicalizedAuthHeader(method, resourceType, resourceId, xmsDate, tokenType, version)
+
+	assert.GreaterOrEqual(t, len(authHeader), 1)
+	assert.Equal(t, expected, authHeader)
+}
+
+func Test_buildCanonicalizedAuthHeaderFromRequest(t *testing.T) {
+	key := "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
+
+	cred, err := NewSharedKeyCredential(key)
+
+	assert.NoError(t, err)
+
+	method := "GET"
+	resourceType := "dbs"
+	resourceId := "dbs/testdb"
+	xmsDate := "Thu, 27 Apr 2017 00:51:12 GMT"
+	tokenType := "master"
+	version := "1.0"
+
+	stringToSign := join(strings.ToLower(method), "\n", strings.ToLower(resourceType), "\n", resourceId, "\n", strings.ToLower(xmsDate), "\n", "", "\n")
+	signature := cred.computeHMACSHA256(stringToSign)
+	expected := url.QueryEscape(fmt.Sprintf("type=%s&ver=%s&sig=%s", tokenType, version, signature))
+
+	req, _ := azruntime.NewRequest(context.TODO(), http.MethodGet, "http://localhost")
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: "dbs/testdb",
+	}
+
+	req.Raw().Header.Set(headerXmsDate, xmsDate)
+	req.Raw().Header.Set(headerXmsVersion, "2020-11-05")
+	req.SetOperationValue(operationContext)
+	authHeader, _ := cred.buildCanonicalizedAuthHeaderFromRequest(req)
+
+	assert.Equal(t, expected, authHeader)
+}
+
+func Test_buildCanonicalizedAuthHeaderFromRequestWithRid(t *testing.T) {
+	key := "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
+
+	cred, err := NewSharedKeyCredential(key)
+
+	assert.NoError(t, err)
+
+	method := "GET"
+	resourceType := "dbs"
+	resourceId := "dbs/rid"
+	xmsDate := "Thu, 27 Apr 2017 00:51:12 GMT"
+	tokenType := "master"
+	version := "1.0"
+
+	stringToSign := join(strings.ToLower(method), "\n", strings.ToLower(resourceType), "\n", resourceId, "\n", strings.ToLower(xmsDate), "\n", "", "\n")
+	signature := cred.computeHMACSHA256(stringToSign)
+	expected := url.QueryEscape(fmt.Sprintf("type=%s&ver=%s&sig=%s", tokenType, version, signature))
+
+	req, _ := azruntime.NewRequest(context.TODO(), http.MethodGet, "http://localhost")
+	operationContext := cosmosOperationContext{
+		resourceType:    resourceTypeDatabase,
+		resourceAddress: "dbs/Rid",
+		isRidBased:      true,
+	}
+
+	req.Raw().Header.Set(headerXmsDate, xmsDate)
+	req.Raw().Header.Set(headerXmsVersion, "2020-11-05")
+	req.SetOperationValue(operationContext)
+	authHeader, _ := cred.buildCanonicalizedAuthHeaderFromRequest(req)
+
+	assert.Equal(t, expected, authHeader)
+}
diff --git a/sdk/data/azcosmos/throughput_properties_test.go b/sdk/data/azcosmos/throughput_properties_test.go
new file mode 100644
index 0000000000..d16faecaf6
--- /dev/null
+++ b/sdk/data/azcosmos/throughput_properties_test.go
@@ -0,0 +1,234 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"encoding/json"
+	"testing"
+	"time"
+)
+
+func TestThroughputPropertiesManualRawSerialization(t *testing.T) {
+	nowAsUnix := time.Unix(1630100602, 0)
+
+	jsonString := []byte("{\"offerType\":\"Invalid\",\"offerResourceId\":\"4SRTANCD3Dw=\",\"offerVersion\":\"V2\",\"content\":{\"offerThroughput\":400},\"id\":\"HFln\",\"_etag\":\"\\\"00000000-0000-0000-9b8c-8ea3e19601d7\\\"\",\"_ts\":1630100602}")
+
+	otherProperties := &ThroughputProperties{}
+	err := json.Unmarshal(jsonString, otherProperties)
+	if err != nil {
+		t.Fatal(err, string(jsonString))
+	}
+
+	if otherProperties.offerType != "Invalid" {
+		t.Errorf("OfferType mismatch %v", otherProperties.offerType)
+	}
+
+	if otherProperties.offerResourceId != "4SRTANCD3Dw=" {
+		t.Errorf("OfferResourceId mismatch %v", otherProperties.offerResourceId)
+	}
+
+	if otherProperties.version != offerVersion2 {
+		t.Errorf("OfferVersion mismatch %v", otherProperties.version)
+	}
+
+	if otherProperties.offerId != "HFln" {
+		t.Errorf("OfferId mismatch %v", otherProperties.offerId)
+	}
+
+	if otherProperties.ETag != "\"00000000-0000-0000-9b8c-8ea3e19601d7\"" {
+		t.Errorf("Etag mismatch %v", otherProperties.ETag)
+	}
+
+	if otherProperties.LastModified.Time != nowAsUnix {
+		t.Errorf("Timestamp mismatch %v", otherProperties.LastModified.Time)
+	}
+
+	mt, err := otherProperties.ManualThroughput()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if mt != 400 {
+		t.Errorf("ManualThroughput mismatch %v", mt)
+	}
+}
+
+func TestThroughputPropertiesManualE2ESerialization(t *testing.T) {
+	nowAsUnix := time.Now().Unix()
+
+	now := UnixTime{
+		Time: time.Unix(nowAsUnix, 0),
+	}
+
+	properties := NewManualThroughputProperties(400)
+	properties.offerId = "HFln"
+	properties.offerResourceId = "4SRTANCD3Dw="
+	properties.ETag = "\"00000000-0000-0000-9b8c-8ea3e19601d7\""
+	properties.LastModified = &now
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	otherProperties := &ThroughputProperties{}
+	err = json.Unmarshal(jsonString, otherProperties)
+	if err != nil {
+		t.Fatal(err, string(jsonString))
+	}
+
+	if otherProperties.offerType != "" {
+		t.Errorf("OfferType mismatch %v", otherProperties.offerType)
+	}
+
+	if otherProperties.offerResourceId != "4SRTANCD3Dw=" {
+		t.Errorf("OfferResourceId mismatch %v", otherProperties.offerResourceId)
+	}
+
+	if otherProperties.version != offerVersion2 {
+		t.Errorf("OfferVersion mismatch %v", otherProperties.version)
+	}
+
+	if otherProperties.offerId != "HFln" {
+		t.Errorf("OfferId mismatch %v", otherProperties.offerId)
+	}
+
+	if otherProperties.ETag != "\"00000000-0000-0000-9b8c-8ea3e19601d7\"" {
+		t.Errorf("Etag mismatch %v", otherProperties.ETag)
+	}
+
+	if otherProperties.LastModified.Time != properties.LastModified.Time {
+		t.Errorf("Timestamp mismatch %v", otherProperties.LastModified.Time)
+	}
+
+	mt, err := otherProperties.ManualThroughput()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if mt != 400 {
+		t.Errorf("ManualThroughput mismatch %v", mt)
+	}
+}
+
+func TestThroughputPropertiesAutoscaleE2ESerialization(t *testing.T) {
+	nowAsUnix := time.Now().Unix()
+
+	now := UnixTime{
+		Time: time.Unix(nowAsUnix, 0),
+	}
+
+	properties := NewAutoscaleThroughputProperties(400)
+	properties.offerId = "HFln"
+	properties.offerResourceId = "4SRTANCD3Dw="
+	properties.ETag = "\"00000000-0000-0000-9b8c-8ea3e19601d7\""
+	properties.LastModified = &now
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	otherProperties := &ThroughputProperties{}
+	err = json.Unmarshal(jsonString, otherProperties)
+	if err != nil {
+		t.Fatal(err, string(jsonString))
+	}
+
+	if otherProperties.offerType != "" {
+		t.Errorf("OfferType mismatch %v", otherProperties.offerType)
+	}
+
+	if otherProperties.offerResourceId != "4SRTANCD3Dw=" {
+		t.Errorf("OfferResourceId mismatch %v", otherProperties.offerResourceId)
+	}
+
+	if otherProperties.version != offerVersion2 {
+		t.Errorf("OfferVersion mismatch %v", otherProperties.version)
+	}
+
+	if otherProperties.offerId != "HFln" {
+		t.Errorf("OfferId mismatch %v", otherProperties.offerId)
+	}
+
+	if otherProperties.ETag != "\"00000000-0000-0000-9b8c-8ea3e19601d7\"" {
+		t.Errorf("Etag mismatch %v", otherProperties.ETag)
+	}
+
+	if otherProperties.LastModified.Time != properties.LastModified.Time {
+		t.Errorf("Timestamp mismatch %v", otherProperties.LastModified.Time)
+	}
+
+	at, err := otherProperties.AutoscaleMaxThroughput()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if at != 400 {
+		t.Errorf("MaxThroughput mismatch %v", at)
+	}
+
+	if otherProperties.offer.AutoScale.AutoscaleAutoUpgradeProperties != nil {
+		t.Errorf("AutoscaleAutoUpgradeProperties mismatch %v", otherProperties.offer.AutoScale.AutoscaleAutoUpgradeProperties)
+	}
+}
+
+func TestThroughputPropertiesAutoscaleIncrementE2ESerialization(t *testing.T) {
+	nowAsUnix := time.Now().Unix()
+
+	now := UnixTime{
+		Time: time.Unix(nowAsUnix, 0),
+	}
+
+	properties := NewAutoscaleThroughputPropertiesWithIncrement(400, 10)
+	properties.offerId = "HFln"
+	properties.offerResourceId = "4SRTANCD3Dw="
+	properties.ETag = "\"00000000-0000-0000-9b8c-8ea3e19601d7\""
+	properties.LastModified = &now
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	otherProperties := &ThroughputProperties{}
+	err = json.Unmarshal(jsonString, otherProperties)
+	if err != nil {
+		t.Fatal(err, string(jsonString))
+	}
+
+	if otherProperties.offerType != "" {
+		t.Errorf("OfferType mismatch %v", otherProperties.offerType)
+	}
+
+	if otherProperties.offerResourceId != "4SRTANCD3Dw=" {
+		t.Errorf("OfferResourceId mismatch %v", otherProperties.offerResourceId)
+	}
+
+	if otherProperties.version != offerVersion2 {
+		t.Errorf("OfferVersion mismatch %v", otherProperties.version)
+	}
+
+	if otherProperties.offerId != "HFln" {
+		t.Errorf("OfferId mismatch %v", otherProperties.offerId)
+	}
+
+	if otherProperties.ETag != "\"00000000-0000-0000-9b8c-8ea3e19601d7\"" {
+		t.Errorf("Etag mismatch %v", otherProperties.ETag)
+	}
+
+	if otherProperties.LastModified.Time != properties.LastModified.Time {
+		t.Errorf("Timestamp mismatch %v", otherProperties.LastModified.Time)
+	}
+
+	at, err := otherProperties.AutoscaleMaxThroughput()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if at != 400 {
+		t.Errorf("MaxThroughput mismatch %v", at)
+	}
+
+	if otherProperties.offer.AutoScale.AutoscaleAutoUpgradeProperties.ThroughputPolicy.IncrementPercent != 10 {
+		t.Errorf("IncrementPercent mismatch %v", otherProperties.offer.AutoScale.AutoscaleAutoUpgradeProperties.ThroughputPolicy.IncrementPercent)
+	}
+}
diff --git a/sdk/data/azcosmos/throughput_request_options_test.go b/sdk/data/azcosmos/throughput_request_options_test.go
new file mode 100644
index 0000000000..9980a7962b
--- /dev/null
+++ b/sdk/data/azcosmos/throughput_request_options_test.go
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"testing"
+)
+
+func TestThroughputRequestOptionsToHeaders(t *testing.T) {
+	options := &ThroughputRequestOptions{}
+	if options.toHeaders() != nil {
+		t.Error("toHeaders should return nil")
+	}
+
+	options.IfMatchEtag = "etag"
+	options.IfNoneMatchEtag = "noneetag"
+	header := options.toHeaders()
+	if header == nil {
+		t.Error("toHeaders should return non-nil")
+	}
+
+	headers := *header
+	if headers[headerIfMatch] != options.IfMatchEtag {
+		t.Errorf("IfMatchEtag not set matching expected %v got %v", options.IfMatchEtag, headers[headerIfMatch])
+	}
+	if headers[headerIfNoneMatch] != options.IfNoneMatchEtag {
+		t.Errorf("IfNoneMatchEtag not set matching expected %v got %v", options.IfNoneMatchEtag, headers[headerIfNoneMatch])
+	}
+}
diff --git a/sdk/data/azcosmos/throughput_response_test.go b/sdk/data/azcosmos/throughput_response_test.go
new file mode 100644
index 0000000000..fb20d1ca52
--- /dev/null
+++ b/sdk/data/azcosmos/throughput_response_test.go
@@ -0,0 +1,142 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package azcosmos
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"testing"
+
+	azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
+)
+
+func TestThroughputResponseParsing(t *testing.T) {
+	properties := NewManualThroughputProperties(400)
+	properties.offerId = "HFln"
+	properties.offerResourceId = "4SRTANCD3Dw="
+	properties.ETag = "\"00000000-0000-0000-9b8c-8ea3e19601d7\""
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody(jsonString),
+		mock.WithHeader(cosmosHeaderEtag, "someEtag"),
+		mock.WithHeader(cosmosHeaderActivityId, "someActivityId"),
+		mock.WithHeader(cosmosHeaderRequestCharge, "13.42"))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+	parsedResponse, err := newThroughputResponse(resp, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if parsedResponse.RawResponse == nil {
+		t.Fatal("parsedResponse.RawResponse is nil")
+	}
+
+	if parsedResponse.ThroughputProperties == nil {
+		t.Fatal("parsedResponse.ThroughputProperties is nil")
+	}
+
+	if parsedResponse.ThroughputProperties.offerId != properties.offerId {
+		t.Fatalf("parsedResponse.ThroughputProperties.offerId is %s, expected %s", parsedResponse.ThroughputProperties.offerId, properties.offerId)
+	}
+
+	if parsedResponse.ThroughputProperties.offerResourceId != properties.offerResourceId {
+		t.Fatalf("parsedResponse.ThroughputProperties.offerResourceId is %s, expected %s", parsedResponse.ThroughputProperties.offerResourceId, properties.offerResourceId)
+	}
+
+	if parsedResponse.ThroughputProperties.ETag != properties.ETag {
+		t.Fatalf("parsedResponse.ThroughputProperties.ETag is %s, expected %s", parsedResponse.ThroughputProperties.ETag, properties.ETag)
+	}
+
+	if parsedResponse.ActivityId() != "someActivityId" {
+		t.Errorf("Expected ActivityId to be %s, but got %s", "someActivityId", parsedResponse.ActivityId())
+	}
+
+	if parsedResponse.RequestCharge() != 13.42 {
+		t.Errorf("Expected RequestCharge to be %f, but got %f", 13.42, parsedResponse.RequestCharge())
+	}
+
+	if parsedResponse.ETag() != "someEtag" {
+		t.Errorf("Expected ETag to be %s, but got %s", "someEtag", parsedResponse.ActivityId())
+	}
+}
+
+func TestThroughputResponseParsingWithPreviousRU(t *testing.T) {
+	var queryRequestCharge float32 = 10.0
+
+	properties := NewManualThroughputProperties(400)
+	properties.offerId = "HFln"
+	properties.offerResourceId = "4SRTANCD3Dw="
+	properties.ETag = "\"00000000-0000-0000-9b8c-8ea3e19601d7\""
+	jsonString, err := json.Marshal(properties)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv, close := mock.NewTLSServer()
+	defer close()
+	srv.SetResponse(
+		mock.WithBody(jsonString),
+		mock.WithHeader(cosmosHeaderEtag, "someEtag"),
+		mock.WithHeader(cosmosHeaderActivityId, "someActivityId"),
+		mock.WithHeader(cosmosHeaderRequestCharge, "13.42"))
+
+	req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pl := azruntime.NewPipeline(srv)
+	resp, _ := pl.Do(req)
+	parsedResponse, err := newThroughputResponse(resp, &queryRequestCharge)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if parsedResponse.RawResponse == nil {
+		t.Fatal("parsedResponse.RawResponse is nil")
+	}
+
+	if parsedResponse.ThroughputProperties == nil {
+		t.Fatal("parsedResponse.ThroughputProperties is nil")
+	}
+
+	if parsedResponse.ThroughputProperties.offerId != properties.offerId {
+		t.Fatalf("parsedResponse.ThroughputProperties.offerId is %s, expected %s", parsedResponse.ThroughputProperties.offerId, properties.offerId)
+	}
+
+	if parsedResponse.ThroughputProperties.offerResourceId != properties.offerResourceId {
+		t.Fatalf("parsedResponse.ThroughputProperties.offerResourceId is %s, expected %s", parsedResponse.ThroughputProperties.offerResourceId, properties.offerResourceId)
+	}
+
+	if parsedResponse.ThroughputProperties.ETag != properties.ETag {
+		t.Fatalf("parsedResponse.ThroughputProperties.ETag is %s, expected %s", parsedResponse.ThroughputProperties.ETag, properties.ETag)
+	}
+
+	if parsedResponse.ActivityId() != "someActivityId" {
+		t.Errorf("Expected ActivityId to be %s, but got %s", "someActivityId", parsedResponse.ActivityId())
+	}
+
+	if parsedResponse.RequestCharge() != 23.42 {
+		t.Errorf("Expected RequestCharge to be %f, but got %f", 23.42, parsedResponse.RequestCharge())
+	}
+
+	if parsedResponse.ETag() != "someEtag" {
+		t.Errorf("Expected ETag to be %s, but got %s", "someEtag", parsedResponse.ActivityId())
+	}
+}