class MU::Cloud::Azure::SDKClient

Generic wrapper for connections to Azure APIs

Attributes

api[R]
issuer[R]
subclass[R]

Public Class Methods

new(api: "Compute", credentials: nil, profile: "Latest", subclass: nil) click to toggle source
# File modules/mu/providers/azure.rb, line 1015
def initialize(api: "Compute", credentials: nil, profile: "Latest", subclass: nil)
  subclass ||= api.sub(/s$/, '')+"Client"
  @subclass = subclass
  @wrapper_semaphore = Mutex.new
  @wrapper_semaphore.synchronize { 
    @wrappers ||= {}
  }

  @credentials = MU::Cloud::Azure.credConfig(credentials, name_only: true)
  @cred_hash = MU::Cloud::Azure.getSDKOptions(credentials)
  if !@cred_hash
    raise MuError, "Failed to load Azure credentials #{credentials ? credentials : "<default>"}"
  end

  # There seem to be multiple ways to get at clients, and different
  # profiles available depending which way you do it, so... try that?
  stdpath = "::Azure::#{api}::Profiles::#{profile}::Mgmt::Client"
  begin
    # Standard approach: get a client from a canned, approved profile
    @api = Object.const_get(stdpath).new(@cred_hash)
  rescue NameError => e
    raise e if !@cred_hash[:client_secret]
    # Weird approach: generate our own credentials object and invoke a
    # client directly from a particular model profile
    token_provider = MsRestAzure::ApplicationTokenProvider.new(
      @cred_hash[:tenant_id],
      @cred_hash[:client_id],
      @cred_hash[:client_secret]
    )
    @cred_obj = MsRest::TokenCredentials.new(token_provider)
    begin
      modelpath = "::Azure::#{api}::Mgmt::#{profile}::#{@subclass}"
      @api = Object.const_get(modelpath).new(@cred_obj)
    rescue NameError
      raise MuError, "Unable to locate a profile #{profile} of Azure API #{api}. I tried:\n#{stdpath}\n#{modelpath}"
    end
  end
end

Public Instance Methods

method_missing(method_sym, *arguments) click to toggle source

For method calls into the Azure API @param method_sym [Symbol] @param arguments [Array]

# File modules/mu/providers/azure.rb, line 1057
def method_missing(method_sym, *arguments)
  aoe_orig = Thread.abort_on_exception
  Thread.abort_on_exception = false
  @wrapper_semaphore.synchronize {
    return @wrappers[method_sym] if @wrappers[method_sym]
  }
  # there's a low-key race condition here, but it's harmless and I'm
  # trying to pin down an odd deadlock condition on cleanup calls
  if !arguments.nil? and arguments.size == 1
    retval = @api.method(method_sym).call(arguments[0])
  elsif !arguments.nil? and arguments.size > 0
    retval = @api.method(method_sym).call(*arguments)
  else
    retval = @api.method(method_sym).call
  end
  deep_retval = ClientCallWrapper.new(retval, method_sym.to_s, self)
  @wrapper_semaphore.synchronize {
    @wrappers[method_sym] ||= deep_retval
  }
  Thread.abort_on_exception = aoe_orig
  return @wrappers[method_sym]
end