private static async Task CoreCleanupAsync(IServiceProvider sp, ITenant rootTenant) { TenantTrackingTenantProviderDecorator tenantTrackingProvider = sp.GetRequiredService <TenantTrackingTenantProviderDecorator>(); List <ITenant> tenants = tenantTrackingProvider.CreatedTenants; tenants.Add(tenantTrackingProvider.Root); ITenantCloudBlobContainerFactory blobContainerFactory = sp.GetRequiredService <ITenantCloudBlobContainerFactory>(); CloudBlobContainer rootContainer = await blobContainerFactory.GetBlobContainerForTenantAsync( rootTenant, TenantProviderBlobStore.ContainerDefinition).ConfigureAwait(false); IEnumerable <CloudBlobContainer> blobContainers = tenants.Select(tenant => { // It would be easier just to ask blobContainerFactory.GetBlobContainerForTenantAsync to give // us the container, but that will attempt to create it if it doesn't exist, and in tests // where we happen already to have deleted it, that quick recreation test will then fail // because Azure doesn't like it if you do taht. string tenantedContainerName = $"{tenant.Id.ToLowerInvariant()}-{TenantProviderBlobStore.ContainerDefinition.ContainerName}"; string containerName = AzureStorageNameHelper.HashAndEncodeBlobContainerName(tenantedContainerName); return(rootContainer.ServiceClient.GetContainerReference(containerName)); }); foreach (CloudBlobContainer container in blobContainers.Distinct(x => x.Name)) { await container.DeleteIfExistsAsync().ConfigureAwait(false); } }
/// <summary> /// Adds services an Azure Blob storage-based implementation of <see cref="ITenantProvider"/>. /// </summary> /// <param name="services">The service collection.</param> /// <param name="getRootTenantStorageConfiguration"> /// A function that returns the <see cref="BlobStorageConfiguration"/> that will be used for the root tenant to /// determine where to store its children. /// </param> /// <returns>The modified service collection.</returns> public static IServiceCollection AddTenantProviderBlobStore( this IServiceCollection services, Func <IServiceProvider, BlobStorageConfiguration> getRootTenantStorageConfiguration) { if (services.Any(s => typeof(ITenantProvider).IsAssignableFrom(s.ServiceType))) { return(services); } services.AddRequiredTenancyServices(); services.AddSingleton(sp => { BlobStorageConfiguration rootTenantStorageConfig = getRootTenantStorageConfiguration(sp); IPropertyBagFactory propertyBagFactory = sp.GetRequiredService <IPropertyBagFactory>(); var rootTenant = new RootTenant(propertyBagFactory); rootTenant.UpdateProperties( values => values.AddBlobStorageConfiguration( TenantProviderBlobStore.ContainerDefinition, rootTenantStorageConfig)); ITenantCloudBlobContainerFactory tenantCloudBlobContainerFactory = sp.GetRequiredService <ITenantCloudBlobContainerFactory>(); IJsonSerializerSettingsProvider serializerSettingsProvider = sp.GetRequiredService <IJsonSerializerSettingsProvider>(); return(new TenantProviderBlobStore(rootTenant, propertyBagFactory, tenantCloudBlobContainerFactory, serializerSettingsProvider)); }); services.AddSingleton <ITenantStore>(sp => sp.GetRequiredService <TenantProviderBlobStore>()); services.AddSingleton <ITenantProvider>(sp => sp.GetRequiredService <TenantProviderBlobStore>()); return(services); }
/// <summary> /// Initializes a new instance of the <see cref="INotificationTemplateStore"/> class. /// </summary> /// <param name="blobContainerFactory">The cloud blob factory.</param> /// <param name="serializerSettingsProvider">The serialization settings provider.</param> /// <param name="logger">The logger.</param> public TenantedAzureBlobTemplateStoreFactory( ITenantCloudBlobContainerFactory blobContainerFactory, IJsonSerializerSettingsProvider serializerSettingsProvider, ILogger <TenantedAzureBlobTemplateStoreFactory> logger) { this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.serializerSettingsProvider = serializerSettingsProvider ?? throw new ArgumentNullException(nameof(serializerSettingsProvider)); this.blobContainerFactory = blobContainerFactory ?? throw new ArgumentNullException(nameof(blobContainerFactory)); }
/// <summary> /// Initializes a new instance of the <see cref="TenantProviderBlobStore"/> class. /// </summary> /// <param name="tenant">The root tenant (registered as a singleton in the container).</param> /// <param name="propertyBagFactory"> /// Enables creation of <see cref="IPropertyBag"/> instances when no existing serialized /// representation exists (i.e., when creating a new tenant), and building of modified property /// bags. /// </param> /// <param name="tenantCloudBlobContainerFactory">The tenanted cloud blob container factory.</param> /// <param name="serializerSettingsProvider">The serializer settings provider for tenant serialization.</param> public TenantProviderBlobStore( RootTenant tenant, IPropertyBagFactory propertyBagFactory, ITenantCloudBlobContainerFactory tenantCloudBlobContainerFactory, IJsonSerializerSettingsProvider serializerSettingsProvider) { ArgumentNullException.ThrowIfNull(tenant); ArgumentNullException.ThrowIfNull(propertyBagFactory); ArgumentNullException.ThrowIfNull(tenantCloudBlobContainerFactory); ArgumentNullException.ThrowIfNull(serializerSettingsProvider); this.Root = tenant; this.tenantCloudBlobContainerFactory = tenantCloudBlobContainerFactory; this.serializerSettings = serializerSettingsProvider.Instance; this.propertyBagFactory = propertyBagFactory; }