class GoodData::Rest::Client

User’s interface to GoodData Platform.

MUST provide way to use - DELETE, GET, POST, PUT SHOULD provide way to use - HEAD, Bulk GET …

Constants

DEFAULT_CONNECTION_IMPLEMENTATION

Constants

DEFAULT_POLL_TIME_LIMIT
DEFAULT_SLEEP_INTERVAL

Attributes

connection[R]

Decide if we need provide direct access to connection

factory[R]

TODO: Decide if we need provide direct access to factory

opts[R]

Public Class Methods

client()
Alias for: connection
connect(username, password = 'aaaa', opts = {}) click to toggle source

Globally available way to connect (and create client and set global instance)

## HACK To make transition from old implementation to new one following HACK IS TEMPORARILY ENGAGED!

  1. First call of connect sets the GoodData::Rest::Client.instance (static, singleton instance)

  2. There are METHOD functions with same signature as their CLASS counterparts using singleton instance

## Example

client = GoodData.connect(‘jon.smith@goodddata.com’, ‘s3cr3tp4sw0rd’)

@param username [String] Username to be used for authentication @param password [String] Password to be used for authentication @return [GoodData::Rest::Client] Client

# File lib/gooddata/rest/client.rb, line 69
def connect(username, password = 'aaaa', opts = {})
  execution_id = ""
  if username.is_a?(Hash) && username.key?(:execution_id)
    execution_id = username[:execution_id]
    username.delete(:execution_id)
  end

  if opts.key?(:execution_id)
    execution_id = opts[:execution_id]
    opts.delete(:execution_id)
  end

  if username.nil? && password.nil?
    username = ENV['GD_GEM_USER']
    password = ENV['GD_GEM_PASSWORD']
  end

  username = GoodData::Helpers.symbolize_keys(username) if username.is_a?(Hash)

  new_opts = opts.dup
  if username.is_a?(Hash) && username.key?(:sst_token)
    new_opts = new_opts.merge(username)
  elsif username.is_a? Hash
    new_opts = new_opts.merge(username)
    new_opts[:username] = username[:login] || username[:user] || username[:username]
    new_opts[:password] = username[:password]
  elsif username.nil? && password.nil? && opts.blank?
    new_opts = Helpers::AuthHelper.read_credentials
  else
    new_opts[:username] = username
    new_opts[:password] = password
  end

  new_opts = { verify_ssl: true, execution_id: execution_id }.merge(new_opts)
  if username.is_a?(Hash) && username[:cookies]
    new_opts[:sst_token] = username[:cookies]['GDCAuthSST']
    new_opts[:cookies] = username[:cookies]
  end

  unless new_opts[:sst_token]
    fail ArgumentError, 'No username specified' if new_opts[:username].nil?
    fail ArgumentError, 'No password specified' if new_opts[:password].nil?
  end

  if username.is_a?(Hash) && username.key?(:server)
    new_opts[:server] = username[:server]
  end

  client = Client.new(new_opts)
  GoodData.logger.info("Connected to server with webdav path #{client.user_webdav_path}")

  # HACK: This line assigns class instance # if not done yet
  @@instance = client # rubocop:disable ClassVars
end
connect_sso(sso) click to toggle source
# File lib/gooddata/rest/client.rb, line 124
def connect_sso(sso)
  @@instance = Client.new(sso) # rubocop:disable ClassVars
end
connection() click to toggle source
# File lib/gooddata/rest/client.rb, line 135
def connection
  @@instance
end
Also aliased as: client
disconnect() click to toggle source
# File lib/gooddata/rest/client.rb, line 128
def disconnect
  if @@instance # rubocop:disable Style/GuardClause
    @@instance.disconnect
    @@instance = nil # rubocop:disable ClassVars
  end
end
new(opts) click to toggle source

Constructor of client @param opts [Hash] Client options @option opts [String] :username Username used for authentication @option opts [String] :password Password used for authentication @option opts :connection_factory Object able to create new instances of GoodData::Rest::Connection @option opts [GoodData::Rest::Connection] :connection Existing GoodData::Rest::Connection

# File lib/gooddata/rest/client.rb, line 153
def initialize(opts)
  # TODO: Decide if we want to pass the options directly or not
  @opts = opts

  @connection_factory = @opts[:connection_factory] || DEFAULT_CONNECTION_IMPLEMENTATION

  # TODO: See previous TODO
  # Create connection
  @connection = opts[:connection] || @connection_factory.new(opts)

  # Connect
  connect

  # Create factory bound to previously created connection
  @factory = ObjectFactory.new(self)
end
retryable(options = {}, &block) click to toggle source

Retry block if exception thrown

# File lib/gooddata/rest/client.rb, line 140
def retryable(options = {}, &block)
  GoodData::Rest::Connection.retryable(options, &block)
end

Public Instance Methods

connect() click to toggle source
# File lib/gooddata/rest/client.rb, line 203
def connect
  username = @opts[:username]
  password = @opts[:password]

  @connection.connect(username, password, @opts)
end
create(klass, data = {}, opts = {}) click to toggle source

Factory stuff

# File lib/gooddata/rest/client.rb, line 229
def create(klass, data = {}, opts = {})
  @factory.create(klass, data, opts)
end
create_datawarehouse(opts = {}) click to toggle source
# File lib/gooddata/rest/client.rb, line 222
def create_datawarehouse(opts = {})
  GoodData::DataWarehouse.create({ client: self }.merge(opts))
end
create_project(options = { title: 'Project' }) click to toggle source
# File lib/gooddata/rest/client.rb, line 170
def create_project(options = { title: 'Project' })
  GoodData::Project.create({ client: self }.merge(options))
end
create_project_from_blueprint(blueprint, options = {}) click to toggle source
# File lib/gooddata/rest/client.rb, line 174
def create_project_from_blueprint(blueprint, options = {})
  GoodData::Model::ProjectCreator.migrate(options.merge(spec: blueprint, client: self))
end
delete(uri, opts = {}) click to toggle source

Rest

HTTP DELETE

@param uri [String] Target URI

# File lib/gooddata/rest/client.rb, line 273
def delete(uri, opts = {})
  @connection.delete uri, opts.merge(stats_on: stats_on?)
end
disconnect() click to toggle source
# File lib/gooddata/rest/client.rb, line 210
def disconnect
  if stats_on?
    GoodData.logger.info("API call statistics to server #{@connection.server}")
    GoodData.logger.info(@connection.stats_table.to_s)
  end
  @connection.disconnect
end
domain(domain_name) click to toggle source
# File lib/gooddata/rest/client.rb, line 178
def domain(domain_name)
  GoodData::Domain[domain_name, :client => self]
end
download(source_relative_path, target_file_path, options = {}) click to toggle source

Downloads file from staging

@param source_relative_path [String] path relative to @param options @param target_file_path [String] path to be downloaded to @param options [Hash] must contain :staging_url key (file will be downloaded from :staging_url + source_relative_path)

# File lib/gooddata/rest/client.rb, line 390
def download(source_relative_path, target_file_path, options = {})
  @connection.download source_relative_path, target_file_path, options
end
download_from_user_webdav(source_relative_path, target_file_path, options = { client: GoodData.client }) click to toggle source
# File lib/gooddata/rest/client.rb, line 394
def download_from_user_webdav(source_relative_path, target_file_path, options = { client: GoodData.client })
  download(source_relative_path, target_file_path, options.merge(:directory => options[:directory],
                                                                 :staging_url => user_webdav_path))
end
find(klass, opts = {}) click to toggle source
# File lib/gooddata/rest/client.rb, line 233
def find(klass, opts = {})
  @factory.find(klass, opts)
end
generate_request_id() click to toggle source
# File lib/gooddata/rest/client.rb, line 263
def generate_request_id
  @connection.generate_request_id
end
get(uri, opts = {}, & block) click to toggle source

HTTP GET

@param uri [String] Target URI

# File lib/gooddata/rest/client.rb, line 280
def get(uri, opts = {}, & block)
  @connection.get uri, opts.merge(stats_on: stats_on?), & block
end
poll_on_code(link, options = {}) click to toggle source

Generalizaton of poller. Since we have quite a variation of how async proceses are handled this is a helper that should help you with resources where the information about “Are we done” is the http code of response. By default we repeat as long as the code == 202. You can change the code if necessary. It expects the URI as an input where it can poll. It returns the value of last poll. In majority of cases these are the data that you need.

@param link [String] Link for polling @param options [Hash] Options @return [Hash] Result of polling

# File lib/gooddata/rest/client.rb, line 317
def poll_on_code(link, options = {})
  code = options[:code] || 202
  process = options[:process]

  response = poll_on_response(link, options.merge(:process => false)) do |resp|
    resp.code == code
  end

  if process == false
    response
  else
    get(link)
  end
end
poll_on_response(link, options = {}, &bl) click to toggle source

Generalizaton of poller. Since we have quite a variation of how async proceses are handled this is a helper that should help you with resources where the information about “Are we done” is inside the response. It expects the URI as an input where it can poll and a block that should return either true (meaning sleep and repeat) or false (meaning we are done). It returns the value of last poll. In majority of cases these are the data that you need

@param link [String] Link for polling @param options [Hash] Options @return [Hash] Result of polling

# File lib/gooddata/rest/client.rb, line 341
def poll_on_response(link, options = {}, &bl)
  time_limit = options[:time_limit] || DEFAULT_POLL_TIME_LIMIT
  process = options[:process] == false ? false : true

  # get the first status and start the timer
  response = get(link, process: process)
  poll_start = Time.now
  retry_time = GoodData::Rest::Connection::RETRY_TIME_INITIAL_VALUE
  while bl.call(response)
    limit_breached = time_limit && (Time.now - poll_start > time_limit)
    if limit_breached
      fail ExecutionLimitExceeded, "The time limit #{time_limit} secs for polling on #{link} is over"
    end
    sleep retry_time
    retry_time *= GoodData::Rest::Connection::RETRY_TIME_COEFFICIENT
    GoodData::Rest::Client.retryable(:tries => Helpers::GD_MAX_RETRY, :refresh_token => proc { connection.refresh_token }) do
      response = get(link, process: process)
    end
  end
  response
end
post(uri, data, opts = {}) click to toggle source

HTTP POST

@param uri [String] Target URI

# File lib/gooddata/rest/client.rb, line 373
def post(uri, data, opts = {})
  @connection.post uri, data, opts.merge(stats_on: stats_on?)
end
processes(id = :all) click to toggle source
# File lib/gooddata/rest/client.rb, line 199
def processes(id = :all)
  GoodData::Process[id, client: self]
end
project_is_accessible?(id) click to toggle source
# File lib/gooddata/rest/client.rb, line 182
def project_is_accessible?(id)
  GoodData.logger.warn 'Beware! project_is_accessible is deprecated and should not be used.'
  begin # rubocop:disable RedundantBegin TODO: remove this after droping JRuby which does not support rescue without begin
    projects(id)
  rescue RestClient::NotFound
    false
  end
end
project_webdav_path(opts = { project: GoodData.project }) click to toggle source
# File lib/gooddata/rest/client.rb, line 284
def project_webdav_path(opts = { project: GoodData.project })
  p = opts[:project]
  fail ArgumentError, 'No :project specified' if p.nil?

  project = GoodData::Project[p, opts]
  fail ArgumentError, 'Wrong :project specified' if project.nil?

  url = project.links['uploads']
  fail 'Project WebDAV not supported in this Data Center' unless url

  GoodData.logger.warn 'Beware! Project webdav is deprecated and should not be used.'
  url
end
projects(id = :all, limit = nil, offset = nil) click to toggle source
# File lib/gooddata/rest/client.rb, line 191
def projects(id = :all, limit = nil, offset = nil)
  if limit.nil?
    GoodData::Project[id, client: self]
  else
    GoodData::Project.all({ client: self }, limit, offset)
  end
end
put(uri, data, opts = {}) click to toggle source

HTTP PUT

@param uri [String] Target URI

# File lib/gooddata/rest/client.rb, line 366
def put(uri, data, opts = {})
  @connection.put uri, data, opts.merge(stats_on: stats_on?)
end
resource(res_name) click to toggle source

Gets resource by name

# File lib/gooddata/rest/client.rb, line 238
def resource(res_name)
  GoodData.logger.info("Getting resource '#{res_name}'")
  nil
end
stats_off() click to toggle source
# File lib/gooddata/rest/client.rb, line 251
def stats_off
  @stats = false
end
stats_on() click to toggle source
# File lib/gooddata/rest/client.rb, line 255
def stats_on
  @stats = true
end
stats_on?() click to toggle source
# File lib/gooddata/rest/client.rb, line 259
def stats_on?
  @stats
end
upload(file, options = {}) click to toggle source

Uploads file to staging

@param file [String] file to be uploaded @param options [Hash] must contain :staging_url key (file will be uploaded to :staging_url + File.basename(file))

# File lib/gooddata/rest/client.rb, line 381
def upload(file, options = {})
  @connection.upload file, options
end
upload_to_user_webdav(file, options = {}) click to toggle source
# File lib/gooddata/rest/client.rb, line 399
def upload_to_user_webdav(file, options = {})
  upload(file, options.merge(:directory => options[:directory],
                             :staging_url => user_webdav_path))
end
user(id = nil) click to toggle source
# File lib/gooddata/rest/client.rb, line 243
def user(id = nil)
  if id
    create(GoodData::Profile, get(id))
  else
    create(GoodData::Profile, @connection.user)
  end
end
user_webdav_path() click to toggle source
# File lib/gooddata/rest/client.rb, line 298
def user_webdav_path
  uri = if opts[:webdav_server]
          opts[:webdav_server]
        else
          links.find { |i| i['category'] == 'uploads' }['link']
        end
  res = uri.chomp('/') + '/'
  res[0] == '/' ? "#{connection.server}#{res}" : res
end
warehouses(id = :all) click to toggle source
# File lib/gooddata/rest/client.rb, line 218
def warehouses(id = :all)
  GoodData::DataWarehouse[id, client: self]
end
with_project(pid, &block) click to toggle source
# File lib/gooddata/rest/client.rb, line 404
def with_project(pid, &block)
  GoodData.with_project(pid, client: self, &block)
end