module Azure::Storage::Common::ClientOptions

Attributes

ca_file[RW]
ssl_max_version[RW]
ssl_min_version[RW]
ssl_version[RW]

Public Class Methods

connection_string_mapping() click to toggle source

The mapping between Storage Connection String items and the options name

@return [Hash]

# File lib/azure/storage/common/client_options.rb, line 153
def self.connection_string_mapping
  @connection_string_mapping ||= {
    "UseDevelopmentStorage" => :use_development_storage,
    "DevelopmentStorageProxyUri" => :development_storage_proxy_uri,
    "DefaultEndpointsProtocol" => :default_endpoints_protocol,
    "AccountName" => :storage_account_name,
    "AccountKey" => :storage_access_key,
    "BlobEndpoint" => :storage_blob_host,
    "TableEndpoint" => :storage_table_host,
    "QueueEndpoint" => :storage_queue_host,
    "FileEndpoint" => :storage_file_host,
    "SharedAccessSignature" => :storage_sas_token,
    "EndpointSuffix" => :storage_dns_suffix
  }
end
env_vars_mapping() click to toggle source

The mapping between Storage Environment Variables and the options name

@return [Hash]

# File lib/azure/storage/common/client_options.rb, line 135
def self.env_vars_mapping
  @env_vars_mapping ||= {
    "EMULATED" => :use_development_storage,
    "AZURE_STORAGE_ACCOUNT" => :storage_account_name,
    "AZURE_STORAGE_ACCESS_KEY" => :storage_access_key,
    "AZURE_STORAGE_CONNECTION_STRING" => :storage_connection_string,
    "AZURE_STORAGE_BLOB_HOST" => :storage_blob_host,
    "AZURE_STORAGE_TABLE_HOST" => :storage_table_host,
    "AZURE_STORAGE_QUEUE_HOST" => :storage_queue_host,
    "AZURE_STORAGE_FILE_HOST" => :storage_file_host,
    "AZURE_STORAGE_SAS_TOKEN" => :storage_sas_token,
    "AZURE_STORAGE_DNS_SUFFIX" => :storage_dns_suffix
  }
end
valid_options() click to toggle source

The valid options for the storage client

@return [Array]

# File lib/azure/storage/common/client_options.rb, line 114
def self.valid_options
  @valid_options ||= [
    :use_development_storage,
    :development_storage_proxy_uri,
    :storage_account_name,
    :storage_access_key,
    :storage_connection_string,
    :storage_sas_token,
    :storage_blob_host,
    :storage_table_host,
    :storage_queue_host,
    :storage_file_host,
    :storage_dns_suffix,
    :default_endpoints_protocol,
    :use_path_style_uri
  ]
end

Public Instance Methods

options() click to toggle source

The options after validated and normalized

@return [Hash]

# File lib/azure/storage/common/client_options.rb, line 107
def options
  @options ||= {}
end
reset!(options = {}) click to toggle source

Public: Reset options for [Azure::Storage::Common::Client]

Attributes

  • options - Hash | String. Optional parameters or storage connection string.

Options

Accepted key/value pairs in options parameter are:

  • :use_development_storage - TrueClass|FalseClass. Whether to use storage emulator.

  • :development_storage_proxy_uri - String. Used with :use_development_storage if emulator is hosted other than localhost.

  • :storage_connection_string - String. The storage connection string.

  • :storage_account_name - String. The name of the storage account.

  • :storage_access_key - Base64 String. The access key of the storage account.

  • :storage_sas_token - String. The signed access signature for the storage account or one of its service.

  • :storage_blob_host - String. Specified Blob serivce endpoint or hostname

  • :storage_table_host - String. Specified Table serivce endpoint or hostname

  • :storage_queue_host - String. Specified Queue serivce endpoint or hostname

  • :storage_dns_suffix - String. The suffix of a regional Storage Serivce, to

  • :default_endpoints_protocol - String. http or https

  • :use_path_style_uri - String. Whether use path style URI for specified endpoints

  • :ca_file - String. File path of the CA file if having issue with SSL

  • :ssl_version - Symbol. The ssl version to be used, sample: :TLSv1_1, :TLSv1_2, for the details, see github.com/ruby/openssl/blob/master/lib/openssl/ssl.rb

  • :ssl_min_version - Symbol. The min ssl version supported, only supported in Ruby 2.5+

  • :ssl_max_version - Symbol. The max ssl version supported, only supported in Ruby 2.5+

The valid set of options include:

  • Storage Emulator: :use_development_storage required, :development_storage_proxy_uri optionally

  • Storage account name and key: :storage_account_name and :storage_access_key required, set :storage_dns_suffix necessarily

  • Storage account name and SAS token: :storage_account_name and :storage_sas_token required, set :storage_dns_suffix necessarily

  • Specified hosts and SAS token: At least one of the service host and SAS token. It's up to user to ensure the SAS token is suitable for the serivce

  • Anonymous Blob: only :storage_blob_host, if it is to only access blobs within a container

Additional notes:

  • Specified hosts can be set when use account name with access key or sas token

  • :default_endpoints_protocol can be set if the scheme is not specified in hosts

  • Storage emulator always use path style URI

When empty options are given, it will try to read settings from Environment Variables. Refer to [Azure::Storage::Common:ClientOptions.env_vars_mapping] for the mapping relationship

@return [Azure::Storage::Common::Client]

# File lib/azure/storage/common/client_options.rb, line 77
def reset!(options = {})
  if options.is_a? String
    options = parse_connection_string(options)
  elsif options.is_a? Hash
    # When the options are provided via singleton setup: Azure::Storage.setup()
    options = setup_options if options.length == 0

    options = parse_connection_string(options[:storage_connection_string]) if options[:storage_connection_string]
  end

  # Load from environment when no valid input
  options = load_env if options.length == 0

  @ca_file = options.delete(:ca_file)
  @ssl_version = options.delete(:ssl_version)
  @ssl_min_version = options.delete(:ssl_min_version)
  @ssl_max_version = options.delete(:ssl_max_version)
  @options = filter(options)
  self.send(:reset_config!, @options) if self.respond_to?(:reset_config!)
  self
end
same_options?(opts) click to toggle source

Check if this client is configured with the same options

# File lib/azure/storage/common/client_options.rb, line 100
def same_options?(opts)
  opts.length == 0 || opts.hash == options.hash
end

Private Instance Methods

filter(opts = {}) click to toggle source
# File lib/azure/storage/common/client_options.rb, line 176
def filter(opts = {})
  results = {}

  # P1 - develpoment storage
  begin
    results = validated_options(opts,
                                required: [:use_development_storage],
                                optional: [:development_storage_proxy_uri])
    results[:use_development_storage] = true
    proxy_uri = results[:development_storage_proxy_uri] ||= StorageServiceClientConstants::DEV_STORE_URI
    results.merge!(storage_account_name: StorageServiceClientConstants::DEVSTORE_STORAGE_ACCOUNT,
                    storage_access_key: StorageServiceClientConstants::DEVSTORE_STORAGE_ACCESS_KEY,
                    storage_blob_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_BLOB_HOST_PORT}",
                    storage_table_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_TABLE_HOST_PORT}",
                    storage_queue_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_QUEUE_HOST_PORT}",
                    storage_file_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_FILE_HOST_PORT}",
                    use_path_style_uri: true)
    return results
  rescue InvalidOptionsError => e
  end

  # P2 - explicit hosts with account connection string
  begin
    results = validated_options(opts,
                                required: [:storage_connection_string],
                                optional: [:use_path_style_uri])
    results[:use_path_style_uri] = results.key?(:use_path_style_uri)
    normalize_hosts(results)
    return results
  rescue InvalidOptionsError => e
  end

  # P3 - account name and key or sas with default hosts or an end suffix
  begin
    results = validated_options(opts,
                                required: [:storage_account_name],
                                only_one: [:storage_access_key, :storage_sas_token, :signer],
                                optional: [:default_endpoints_protocol, :storage_dns_suffix])
    protocol = results[:default_endpoints_protocol] ||= StorageServiceClientConstants::DEFAULT_PROTOCOL
    suffix = results[:storage_dns_suffix] ||= StorageServiceClientConstants::DEFAULT_ENDPOINT_SUFFIX
    account = results[:storage_account_name]
    results.merge!(storage_blob_host: "#{protocol}://#{account}.#{ServiceType::BLOB}.#{suffix}",
                    storage_table_host: "#{protocol}://#{account}.#{ServiceType::TABLE}.#{suffix}",
                    storage_queue_host: "#{protocol}://#{account}.#{ServiceType::QUEUE}.#{suffix}",
                    storage_file_host: "#{protocol}://#{account}.#{ServiceType::FILE}.#{suffix}",
                    use_path_style_uri: false)
    return results
  rescue InvalidOptionsError => e
  end

  # P4 - explicit hosts with account name and key
  begin
    results = validated_options(opts,
                                required: [:storage_account_name, :storage_access_key],
                                at_least_one: [:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host],
                                optional: [:use_path_style_uri, :default_endpoints_protocol])
    results[:use_path_style_uri] = results.key?(:use_path_style_uri)
    normalize_hosts(results)
    return results
  rescue InvalidOptionsError => e
  end

  # P5 - anonymous or sas only for one or more particular services, options with account name/key + hosts should be already validated in P4
  begin
    results = validated_options(opts,
                                at_least_one: [:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host],
                                optional: [:use_path_style_uri, :default_endpoints_protocol, :storage_sas_token])
    results[:use_path_style_uri] = results.key?(:use_path_style_uri)
    normalize_hosts(results)
    # Adds anonymous signer if no sas token
    results[:signer] = Azure::Storage::Common::Core::Auth::AnonymousSigner.new unless results.key?(:storage_sas_token)
    return results
  rescue InvalidOptionsError => e
  end

  # P6 - account name and key or sas with explicit hosts
  begin
    results = validated_options(opts,
                                required: [:storage_account_name],
                                only_one: [:storage_access_key, :storage_sas_token],
                                at_least_one: [:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host])
    results[:use_path_style_uri] = results.key?(:use_path_style_uri)
    normalize_hosts(results)
    return results
  rescue InvalidOptionsError => e
  end

  raise InvalidOptionsError, "options provided are not valid set: #{opts}" # wrong opts if move to this line
end
is_base64_encoded() click to toggle source
# File lib/azure/storage/common/client_options.rb, line 277
def is_base64_encoded
  Proc.new do |i|
    i.is_a?(String) && i =~ /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/
  end
end
is_non_empty_string() click to toggle source
# File lib/azure/storage/common/client_options.rb, line 294
def is_non_empty_string
  Proc.new { |i| i && i.is_a?(String) && i.strip.length }
end
is_true() click to toggle source
# File lib/azure/storage/common/client_options.rb, line 290
def is_true
  Proc.new { |i| i == true || (i.is_a?(String) && i.downcase == "true") }
end
is_url() click to toggle source
# File lib/azure/storage/common/client_options.rb, line 283
def is_url
  Proc.new do |i|
    i = "http://" + i unless i =~ /\Ahttps?:\/\//
    i =~ URI.regexp(["http", "https"])
  end
end
load_env() click to toggle source
# File lib/azure/storage/common/client_options.rb, line 338
def load_env
  cs = ENV["AZURE_STORAGE_CONNECTION_STRING"]
  return parse_connection_string(cs) if cs

  opts = {}
  ClientOptions.env_vars_mapping.each { |k, v| opts[v] = ENV[k] if ENV[k] }
  opts
end
method_missing(method_name, *args, &block) click to toggle source
Calls superclass method
# File lib/azure/storage/common/client_options.rb, line 171
def method_missing(method_name, *args, &block)
  return super unless options.key? method_name
  options[method_name]
end
normalize_hosts(options) click to toggle source
# File lib/azure/storage/common/client_options.rb, line 266
def normalize_hosts(options)
  if options[:default_endpoints_protocol]
    [:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host].each do |k|
      if options[k]
        raise InvalidOptionsError, "Explict host cannot contain scheme if default_endpoints_protocol is set." if options[k] =~ /^https?/
        options[k] = "#{options[:default_endpoints_protocol]}://#{options[k]}"
      end
    end
  end
end
parse_connection_string(connection_string) click to toggle source
# File lib/azure/storage/common/client_options.rb, line 347
def parse_connection_string(connection_string)
  opts = {}
  connection_string.split(";").each do |i|
    e = i.index("=")
    raise InvalidConnectionStringError, Azure::Storage::Common::Core::SR::INVALID_CONNECTION_STRING if e < 0 || e == i.length - 1
    key, value = i[0..e - 1], i[e + 1..i.length - 1]
    raise InvalidConnectionStringError, Azure::Storage::Common::Core::SR::INVALID_CONNECTION_STRING_BAD_KEY % key unless ClientOptions.connection_string_mapping.key? key
    raise InvalidConnectionStringError, Azure::Storage::Common::Core::SR::INVALID_CONNECTION_STRING_EMPTY_KEY % key if value.length == 0
    raise InvalidConnectionStringError, Azure::Storage::Common::Core::SR::INVALID_CONNECTION_STRING_DUPLICATE_KEY % key if opts.key? key
    opts[ClientOptions.connection_string_mapping[key]] = value
  end
  raise InvalidConnectionStringError, Azure::Storage::Common::Core::SR::INVALID_CONNECTION_STRING if opts.length == 0

  opts
end
validated_options(opts, requirements = {}) click to toggle source
# File lib/azure/storage/common/client_options.rb, line 298
def validated_options(opts, requirements = {})
  raise InvalidOptionsError, 'nil is not allowed for option\'s value' if opts.values.any? { |v| v == nil }
  required = requirements[:required] || []
  at_least_one = requirements[:at_least_one] || []
  only_one = requirements[:only_one] || []
  optional = requirements[:optional] || []

  raise InvalidOptionsError, "Not all required keys are provided: #{required}" if required.any? { |k| !opts.key? k }
  raise InvalidOptionsError, "Only one of #{only_one} is required" unless only_one.length == 0 || only_one.count { |k| opts.key? k } == 1
  raise InvalidOptionsError, "At least one of #{at_least_one} is required" unless at_least_one.length == 0 || at_least_one.any? { |k| opts.key? k }

  @@option_validators ||= {
    use_development_storage: is_true,
    development_storage_proxy_uri: is_url,
    storage_account_name: lambda { |i| i.is_a?(String) },
    storage_access_key: is_base64_encoded,
    storage_sas_token: lambda { |i| i.is_a?(String) },
    storage_blob_host: is_url,
    storage_table_host: is_url,
    storage_queue_host: is_url,
    storage_file_host: is_url,
    storage_dns_suffix: is_url,
    default_endpoints_protocol: lambda { |i| ["http", "https"].include? i.downcase },
    use_path_style_uri: is_true,
    signer: lambda { |i| i.is_a? Azure::Core::Auth::Signer} 
  }

  valid_options = required + at_least_one + only_one + optional
  results = {}

  opts.each do |k, v|
    raise InvalidOptionsError, "#{k} is not included in valid options" unless valid_options.length == 0 || valid_options.include?(k)
    unless @@option_validators.key?(k) && @@option_validators[k].call(v)
      raise InvalidOptionsError, "#{k} is invalid"
    end
    results[k] = v
  end
  results
end