From 34e168956354e7117a73fcf12d4b425a6d28dc66 Mon Sep 17 00:00:00 2001 From: Luca Ongaro Date: Mon, 25 Nov 2024 11:34:33 +0100 Subject: [PATCH] Initialize signer lazily By initializing the signer lazily, only when used the first time, we also postpone the check for missing `secret_key` and `principal_id`. This makes it possible to load the Rails environment without setting the Azure Storage credentials in environments that do not need to connect to Azure. For example, a build step that precompiles assets needs to load the environments, but usually does not need Azure Storage. Before this change, one would still have to set some (possibly fake) `secret_key` or `principal_id` in such build step, while with this change those can be omitted in any situation in which no real calls to the Azure API will be made. --- lib/azure_blob/client.rb | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/azure_blob/client.rb b/lib/azure_blob/client.rb index c6235ba..0fdbd1f 100644 --- a/lib/azure_blob/client.rb +++ b/lib/azure_blob/client.rb @@ -20,18 +20,9 @@ def initialize(account_name:, access_key: nil, principal_id: nil, container:, ho @container = container @host = host @cloud_regions = options[:cloud_regions]&.to_sym || :global - - no_access_key = access_key.nil? || access_key&.empty? - using_managed_identities = no_access_key && !principal_id.nil? || options[:use_managed_identities] - - if !using_managed_identities && no_access_key - raise AzureBlob::Error.new( - "`access_key` cannot be empty. To use managed identities instead, pass a `principal_id` or set `use_managed_identities` to true." - ) - end - @signer = using_managed_identities ? - AzureBlob::EntraIdSigner.new(account_name:, host: self.host, principal_id:) : - AzureBlob::SharedKeySigner.new(account_name:, access_key:, host: self.host) + @access_key = access_key + @principal_id = principal_id + @use_managed_identities = options[:use_managed_identities] end # Create a blob of type block. Will automatically split the the blob in multiple block and send the blob in pieces (blocks) if the blob is too big. @@ -364,6 +355,24 @@ def host @host ||= "https://#{account_name}.blob.#{CLOUD_REGIONS_SUFFIX[cloud_regions]}" end - attr_reader :account_name, :signer, :container, :http, :cloud_regions + def signer + @signer ||= + begin + no_access_key = access_key.nil? || access_key&.empty? + using_managed_identities = no_access_key && !principal_id.nil? || use_managed_identities + + if !using_managed_identities && no_access_key + raise AzureBlob::Error.new( + "`access_key` cannot be empty. To use managed identities instead, pass a `principal_id` or set `use_managed_identities` to true." + ) + end + + using_managed_identities ? + AzureBlob::EntraIdSigner.new(account_name:, host:, principal_id:) : + AzureBlob::SharedKeySigner.new(account_name:, access_key:, host:) + end + end + + attr_reader :account_name, :container, :http, :cloud_regions, :access_key, :principal_id, :use_managed_identities end end