public void ParsePreferredLocations_WithEntries()
        {
            // Arrange
            string preferredLocationsWithEntries = "East US, North Europe,";

            // Act
            var parsedLocations = CosmosDBUtility.ParsePreferredLocations(preferredLocationsWithEntries);

            // Assert
            Assert.Equal(2, parsedLocations.Count());
        }
 private static async Task CreateLeaseCollectionIfNotExistsAsync(IDocumentClient leaseDocumentClient, string databaseName, string collectionName, int throughput)
 {
     try
     {
         await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(leaseDocumentClient, databaseName, collectionName, null, throughput);
     }
     catch (DocumentClientException ex) when(ex.Message.Contains(SharedThroughputRequirementException))
     {
         await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(leaseDocumentClient, databaseName, collectionName, LeaseCollectionRequiredPartitionKey, throughput);
     }
 }
        public void ParsePreferredLocations_WhenEmpty()
        {
            // Arrange
            string preferredLocationsEmpty = string.Empty;
            string preferredLocationsNull  = null;

            // Act
            var parsedLocationsEmpty = CosmosDBUtility.ParsePreferredLocations(preferredLocationsEmpty);
            var parsedLocationsNull  = CosmosDBUtility.ParsePreferredLocations(preferredLocationsNull);

            // Assert
            Assert.Empty(parsedLocationsEmpty);
            Assert.Empty(parsedLocationsNull);
        }
예제 #4
0
        public async Task CreateIfNotExist_Succeeds()
        {
            // Arrange
            var             mockService = new Mock <ICosmosDBService>(MockBehavior.Strict);
            CosmosDBContext context     = CosmosDBTestUtility.CreateContext(mockService.Object);

            CosmosDBTestUtility.SetupDatabaseMock(mockService);
            CosmosDBTestUtility.SetupCollectionMock(mockService);

            // Act
            await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(context);

            // Assert
            mockService.VerifyAll();
        }
예제 #5
0
        public async Task CreateIfNotExists_DoesNotSetThroughput_IfZero()
        {
            // Arrange
            var mockService = new Mock <ICosmosDBService>(MockBehavior.Strict);
            var context     = CosmosDBTestUtility.CreateContext(mockService.Object, throughput: 0);

            CosmosDBTestUtility.SetupDatabaseMock(mockService);
            CosmosDBTestUtility.SetupCollectionMock(mockService);

            // Act
            await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(context);

            // Assert
            mockService.VerifyAll();
        }
예제 #6
0
        public async Task CreateIfNotExists_SetsPartitionKey_IfSpecified()
        {
            // Arrange
            string partitionKeyPath = "partitionKey";
            var    mockService      = new Mock <ICosmosDBService>(MockBehavior.Strict);
            var    context          = CosmosDBTestUtility.CreateContext(mockService.Object, partitionKeyPath: partitionKeyPath);

            CosmosDBTestUtility.SetupDatabaseMock(mockService);
            CosmosDBTestUtility.SetupCollectionMock(mockService, partitionKeyPath);

            // Act
            await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(context);

            // Assert
            mockService.VerifyAll();
        }
        public void BuildConnectionPolicy()
        {
            // Arrange
            string preferredLocationsWithEntries = "East US, North Europe,";
            bool   useMultiMaster = true;
            string userAgent      = Guid.NewGuid().ToString();

            // Act
            var policy = CosmosDBUtility.BuildConnectionPolicy(Documents.Client.ConnectionMode.Direct, Documents.Client.Protocol.Tcp, preferredLocationsWithEntries, useMultiMaster, userAgent);

            // Assert
            Assert.Equal(userAgent, policy.UserAgentSuffix);
            Assert.Equal(useMultiMaster, policy.UseMultipleWriteLocations);
            Assert.Equal(Documents.Client.ConnectionMode.Direct, policy.ConnectionMode);
            Assert.Equal(Documents.Client.Protocol.Tcp, policy.ConnectionProtocol);
            Assert.Equal(2, policy.PreferredLocations.Count);
        }
예제 #8
0
        public CosmosDBConfigStorage(ConfigGenConfiguration configGenConfiguration, IKeyVaultClient keyvaultClient)
        {
            string keyVaultName = configGenConfiguration[Constants.ConfigSettingName_ServiceKeyVaultName];

            string connectionString = keyvaultClient
                                      .ResolveSecretUriAsync(configGenConfiguration[ConfigSettingName_DesignTimeCosmosDBConnectionString])
                                      .Result;

            Ensure.NotNull(connectionString, "connectionString");

            string dbName = keyvaultClient
                            .ResolveSecretUriAsync(configGenConfiguration[ConfigSettingName_DesignTimeCosmosDBDatabaseName])
                            .Result;

            Ensure.NotNull(dbName, "dbName");

            _db = new CosmosDBUtility(connectionString, dbName);
        }
예제 #9
0
        public async Task CreateIfNotExist_Rethrows()
        {
            // Arrange
            var             mockService = new Mock <ICosmosDBService>(MockBehavior.Strict);
            CosmosDBContext context     = CosmosDBTestUtility.CreateContext(mockService.Object);

            CosmosDBTestUtility.SetupDatabaseMock(mockService);

            // overwrite the default setup with one that throws
            mockService
            .Setup(m => m.CreateDatabaseIfNotExistsAsync(It.Is <Database>(d => d.Id == CosmosDBTestUtility.DatabaseName)))
            .ThrowsAsync(CosmosDBTestUtility.CreateDocumentClientException(HttpStatusCode.BadRequest));

            // Act
            await Assert.ThrowsAsync <DocumentClientException>(
                () => CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(context));

            // Assert
            mockService.VerifyAll();
        }
예제 #10
0
        public CosmosDbConfigurationProvider(IKeyVaultClient kv)
        {
            async Task <string> resolveKey(string configSettingName)
            {
                var key = InitialConfiguration.Get(configSettingName);

                Ensure.NotNull(key, configSettingName);
                var value = await kv.ResolveSecretUriAsync(key);

                Ensure.NotNull(value, "resolved_" + configSettingName);
                return(value);
            }

            var connectionString = resolveKey(ConfigSettingName_CosmosDBConfig_ConnectionString).Result;
            var dbName           = resolveKey(ConfigSettingName_CosmosDBConfig_DatabaseName).Result;
            var collectionName   = resolveKey(ConfigSettingName_CosmosDBConfig_CollectionName).Result;

            var cosmosDBUtil       = new CosmosDBUtility(connectionString, dbName);
            var settings           = cosmosDBUtil.FindOne(collectionName).Result;
            var settingsDictionary = DeserializeToDictionary(settings);

            _settings = new Dictionary <string, string>(settingsDictionary.Select(x => KeyValuePair.Create <string, string>(x.Key, x.Value.ToString())));
        }
        public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var parameter = context.Parameter;
            var attribute = parameter.GetCustomAttribute <CosmosStoreTriggerAttribute>(inherit: false);

            if (attribute == null)
            {
                return(null);
            }

            var desiredConnectionMode     = _bindingOptions.ConnectionMode;
            var desiredConnectionProtocol = _bindingOptions.Protocol;

            DocumentCollectionInfo documentCollectionLocation;
            DocumentCollectionInfo leaseCollectionLocation;
            var processorOptions = BuildProcessorOptions(attribute);

            processorOptions.StartFromBeginning = attribute.StartFromBeginning;
            if (attribute.MaxItemsPerInvocation > 0)
            {
                processorOptions.MaxItemCount = attribute.MaxItemsPerInvocation;
            }

            IDocumentClient monitoredDocumentClient;
            IDocumentClient leaseDocumentClient;

            try
            {
                var monitoredConnectionString = ResolveConnectionString(attribute.ConnectionStringSetting, nameof(CosmosStoreTriggerAttribute.ConnectionStringSetting));
                if (string.IsNullOrEmpty(monitoredConnectionString))
                {
                    throw new InvalidOperationException("The connection string for the monitored collection is in an invalid format, please use AccountEndpoint=XXXXXX;AccountKey=XXXXXX;.");
                }

                var monitoredCosmosDbConnectionString = new CosmosDBConnectionString(monitoredConnectionString);

                var leasesConnectionString = ResolveAttributeLeasesConnectionString(attribute);
                var leasesConnection       = new CosmosDBConnectionString(leasesConnectionString);
                if (leasesConnection.ServiceEndpoint == null)
                {
                    throw new InvalidOperationException("The connection string for the leases collection is in an invalid format, please use AccountEndpoint=XXXXXX;AccountKey=XXXXXX;.");
                }

                var monitoredCollectionName = GetMonitoredCollectionName(attribute);

                documentCollectionLocation = new DocumentCollectionInfo
                {
                    Uri              = monitoredCosmosDbConnectionString.ServiceEndpoint,
                    MasterKey        = monitoredCosmosDbConnectionString.AuthKey,
                    DatabaseName     = ResolveAttributeValue(attribute.DatabaseName),
                    CollectionName   = monitoredCollectionName,
                    ConnectionPolicy = { UserAgentSuffix = CosmosStoreTriggerUserAgentSuffix }
                };

                if (desiredConnectionMode.HasValue)
                {
                    documentCollectionLocation.ConnectionPolicy.ConnectionMode = desiredConnectionMode.Value;
                }

                if (desiredConnectionProtocol.HasValue)
                {
                    documentCollectionLocation.ConnectionPolicy.ConnectionProtocol = desiredConnectionProtocol.Value;
                }

                leaseCollectionLocation = new DocumentCollectionInfo
                {
                    Uri            = leasesConnection.ServiceEndpoint,
                    MasterKey      = leasesConnection.AuthKey,
                    DatabaseName   = ResolveAttributeValue(attribute.LeaseDatabaseName),
                    CollectionName = ResolveAttributeValue(attribute.LeaseCollectionName)
                };

                leaseCollectionLocation.ConnectionPolicy.UserAgentSuffix = CosmosStoreTriggerUserAgentSuffix;

                if (desiredConnectionMode.HasValue)
                {
                    leaseCollectionLocation.ConnectionPolicy.ConnectionMode = desiredConnectionMode.Value;
                }

                if (desiredConnectionProtocol.HasValue)
                {
                    leaseCollectionLocation.ConnectionPolicy.ConnectionProtocol = desiredConnectionProtocol.Value;
                }

                var resolvedPreferredLocations = ResolveAttributeValue(attribute.PreferredLocations);
                foreach (var location in CosmosDBUtility.ParsePreferredLocations(resolvedPreferredLocations))
                {
                    documentCollectionLocation.ConnectionPolicy.PreferredLocations.Add(location);
                    leaseCollectionLocation.ConnectionPolicy.PreferredLocations.Add(location);
                }

                if (string.IsNullOrEmpty(documentCollectionLocation.DatabaseName) ||
                    string.IsNullOrEmpty(documentCollectionLocation.CollectionName) ||
                    string.IsNullOrEmpty(leaseCollectionLocation.DatabaseName) ||
                    string.IsNullOrEmpty(leaseCollectionLocation.CollectionName))
                {
                    throw new InvalidOperationException("Cannot establish database and collection values. If you are using environment and configuration values, please ensure these are correctly set.");
                }

                if (documentCollectionLocation.Uri.Equals(leaseCollectionLocation.Uri) &&
                    documentCollectionLocation.DatabaseName.Equals(leaseCollectionLocation.DatabaseName) &&
                    documentCollectionLocation.CollectionName.Equals(leaseCollectionLocation.CollectionName))
                {
                    throw new InvalidOperationException("The monitored collection cannot be the same as the collection storing the leases.");
                }

                var cosmosStore = new CosmosStore <T>(new CosmosStoreSettings(documentCollectionLocation.DatabaseName,
                                                                              documentCollectionLocation.Uri, documentCollectionLocation.MasterKey),
                                                      attribute.CollectionName);

                monitoredDocumentClient = cosmosStore.CosmonautClient.DocumentClient;

                leaseDocumentClient = new DocumentClient(leasesConnection.ServiceEndpoint, leasesConnection.AuthKey, leaseCollectionLocation.ConnectionPolicy);

                if (attribute.CreateLeaseCollectionIfNotExists)
                {
                    await CreateLeaseCollectionIfNotExistsAsync(leaseDocumentClient, leaseCollectionLocation.DatabaseName, leaseCollectionLocation.CollectionName, attribute.LeasesCollectionThroughput);
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                          $"Cannot create Collection Information for {attribute.CollectionName} in database {attribute.DatabaseName} with lease {attribute.LeaseCollectionName} in database {attribute.LeaseDatabaseName} : {ex.Message}", ex);
            }

            return(new CosmosStoreTriggerBinding <T>(parameter, documentCollectionLocation, leaseCollectionLocation, monitoredDocumentClient, leaseDocumentClient, processorOptions, _logger));
        }