robinrodricks / FluentStorage

A polycloud .NET cloud storage abstraction layer. Provides Blob storage (AWS S3, GCP, FTP, SFTP, Azure Blob/File/Event Hub/Data Lake) and Messaging (AWS SQS, Azure Queue/ServiceBus). Supports .NET 5+ and .NET Standard 2.0+. Pure C#.
MIT License
302 stars 40 forks source link

Azure Datalake Blob storage gen2 fails to connect [COMMUNITY HELP WANTED] #41

Open dev1010101 opened 1 year ago

dev1010101 commented 1 year ago

Problem: Try to create a blob connection azure blobstorage gen2 with FromConnectionString did the StorageFactory.Modules.UseAzureBlobStorage() to register the azure blob storage extention throws a NullReferenceException

Cause: ExtendedSdk.GetHttpPipeline(BlobServiceClient sdkClient) is using internals of Azure BlobServiceClient and they have changed I assume.

This ugly hack did the trick:

            var accountName = <<StorageAccountName>>;
            var credential = new StorageSharedKeyCredential(accountName ,<<accessToken>>);

            var uri = new Uri($"https://{accountName}.blob.core.windows.net/");
            var client = new BlobServiceClient(uri, credential);

            FieldInfo BlobClientConfigurationField =
                typeof(BlobServiceClient).GetField("_clientConfiguration", BindingFlags.NonPublic | BindingFlags.Instance);

            var clientConfig = BlobClientConfigurationField.GetValue(client);
            var clientConfigType = clientConfig.GetType();
            PropertyInfo httpPipelineProperty =
                clientConfigType.GetProperty("Pipeline", BindingFlags.Public | BindingFlags.Instance);

            Azure.Core.Pipeline.HttpPipeline httpPipeline = httpPipelineProperty.GetValue(clientConfig) as Azure.Core.Pipeline.HttpPipeline;

            Type AzureDataLakeStorageType = typeof(IBlobStorage)
                .Assembly.GetType("FluentStorage.Azure.Blobs.AzureDataLakeStorage");
            // ConstructorInfo method = t.GetConstructor(new Type[] { typeof(BlobServiceClient), typeof(string), typeof(StorageSharedKeyCredential), typeof(string )} );
            //# Object o = method.Invoke(new Object[] {client, accountName, credential, null});
            Type extendedSdkType = typeof(IBlobStorage)
                .Assembly.GetType("Blobs.ExtendedSdk");

            var dlStorage = FormatterServices.GetUninitializedObject(AzureDataLakeStorageType);
            var extendedSdk = FormatterServices.GetUninitializedObject(extendedSdkType);

            var sdkClientField =
                extendedSdkType.GetField("_sdkClient", BindingFlags.Instance | BindingFlags.NonPublic);
            var pipelineField = extendedSdkType.GetField("_httpPipeline", BindingFlags.Instance | BindingFlags.NonPublic);
            var dsfBaseAddress = extendedSdkType.GetField("_dfsBaseAddress", BindingFlags.Instance | BindingFlags.NonPublic);

            sdkClientField.SetValue(extendedSdk, client);
            pipelineField.SetValue(extendedSdk, httpPipeline);
            dsfBaseAddress.SetValue(extendedSdk, $"https://{accountName}.dfs.core.windows.net/");

            var extendedField = AzureDataLakeStorageType.GetField("_extended", BindingFlags.Instance | BindingFlags.NonPublic);
            extendedField.SetValue(dlStorage, extendedSdk);

            var clientField2 = AzureDataLakeStorageType.BaseType.GetField("_client", BindingFlags.Instance | BindingFlags.NonPublic);
            clientField2.SetValue(dlStorage, client);

            var sasCredField = AzureDataLakeStorageType.BaseType.GetField("_sasSigningCredentials", BindingFlags.Instance | BindingFlags.NonPublic);
            sasCredField.SetValue(dlStorage, credential);

            var containerField = AzureDataLakeStorageType.BaseType.GetField("_containerNameToContainerClient", BindingFlags.Instance | BindingFlags.NonPublic);
            containerField.SetValue(dlStorage, new ConcurrentDictionary<string, BlobContainerClient>());
robinrodricks commented 1 year ago

Can you possibly file a PR with a fix and submit it? I would love to add a fix for this into the main library.

robinrodricks commented 3 months ago

Since you are not responding, I have tried to implement a fix and released it myself:

https://www.nuget.org/packages/FluentStorage/5.5.1 https://www.nuget.org/packages/FluentStorage.Azure.Blobs/5.2.5

robinrodricks commented 3 months ago

PUBLIC NOTICE!

I would request the community to test an Azure DataLake Gen2 with FluentStorage and let me know if it works.