class GoodData::Process

Attributes

data[R]
json[R]
raw_data[R]
to_hash[R]

Public Class Methods

[](id, options = { :client => GoodData.connection }) click to toggle source
# File lib/gooddata/models/process.rb, line 26
def [](id, options = { :client => GoodData.connection })
  project = options[:project]
  client = options[:client] || (project && project.client)
  fail 'Client has to be specified in options' unless client

  if id == :all && project
    uri = "/gdc/projects/#{project.pid}/dataload/processes"
    data = client.get(uri)
    data['processes']['items'].map do |process_data|
      client.create(Process, process_data, project: project)
    end
  elsif id == :all
    uri = "/gdc/account/profile/#{client.user.obj_id}/dataload/processes"
    data = client.get(uri)
    pids = data['processes']['items'].map { |process_data| process_data['process']['links']['self'].match(%r{/gdc/projects/(\w*)/})[1] }.uniq
    projects_lookup = pids.pmap { |pid| client.projects(pid) }.reduce({}) do |a, e|
      a[e.pid] = e
      a
    end

    data['processes']['items'].map do |process_data|
      pid = process_data['process']['links']['self'].match(%r{/gdc/projects/(\w*)/})[1]
      client.create(Process, process_data, project: projects_lookup[pid])
    end
  else
    uri = "/gdc/projects/#{project.pid}/dataload/processes/#{id}"
    client.create(Process, client.get(uri), project: project)
  end
end
all() click to toggle source
# File lib/gooddata/models/process.rb, line 56
def all
  Process[:all]
end
deploy(path, options = { client: GoodData.client, project: GoodData.project }) click to toggle source

Deploy a new process or redeploy existing one.

@param path [String] Path to ZIP archive or to a directory containing files that should be ZIPed @option options [String] :files_to_exclude @option options [String] :type (‘GRAPH’) Type of process - GRAPH or RUBY @option options [String] :name Readable name of the process @option options [String] :process_id ID of a process to be redeployed (do not set if you want to create a new process) @option options [Boolean] :verbose (false) Switch on verbose mode for detailed logging

# File lib/gooddata/models/process.rb, line 93
def deploy(path, options = { client: GoodData.client, project: GoodData.project })
  if path.is_a?(Hash) && path[:component]
    deploy_component path, options
  elsif path.to_s.start_with?(APP_STORE_URL)
    deploy_brick path, options
  elsif path.to_s =~ %r{\${.*}:(.*)\/(.*):\/}
    deploy_from_appstore path.to_s, options
  else
    deploy_simple_process path, options
  end
end
deploy_brick(path, options = { :client => GoodData.client, :project => GoodData.project }) click to toggle source
# File lib/gooddata/models/process.rb, line 134
def deploy_brick(path, options = { :client => GoodData.client, :project => GoodData.project })
  client, project = GoodData.get_client_and_project(options)

  brick_uri_parts = URI(path).path.split('/')
  ref = brick_uri_parts[4]
  brick_name = brick_uri_parts.last
  brick_path = brick_uri_parts[5..-1].join('/')

  Dir.mktmpdir do |dir|
    Dir.chdir(dir) do
      `git clone #{APP_STORE_URL}`
    end

    Dir.chdir(File.join(dir, 'app_store')) do
      if ref
        `git checkout #{ref}`

        fail 'Wrong branch or tag specified!' if $CHILD_STATUS.to_i.nonzero?
      end

      opts = {
        :client => client,
        :project => project,
        :name => brick_name,
        :type => 'RUBY'
      }

      full_brick_path = File.join(dir, 'app_store', brick_path)

      fail "Invalid brick name specified - '#{brick_name}'" unless File.exist?(full_brick_path)

      return deploy(full_brick_path, opts)
    end
  end
end
deploy_component(data, options = { client: GoodData.client, project: GoodData.project }) click to toggle source
# File lib/gooddata/models/process.rb, line 189
def deploy_component(data, options = { client: GoodData.client, project: GoodData.project })
  client, project = GoodData.get_client_and_project(options)
  data = { process: data } unless data[:process]
  data[:process] = GoodData::Helpers.symbolize_keys(data[:process]).select { |k| %i[type name component dataSources].include? k }
  data[:process][:component] = GoodData::Helpers.symbolize_keys(data[:process][:component]).select { |k| %i[name version configLocation config].include? k }

  save(data, options)
end
deploy_from_appstore(path, options = { :client => GoodData.client, :project => GoodData.project }) click to toggle source
# File lib/gooddata/models/process.rb, line 170
def deploy_from_appstore(path, options = { :client => GoodData.client, :project => GoodData.project })
  deploy_name = options[:name] || "Process of #{path}"

  verbose = options[:verbose] || false
  GoodData.logger.info("Deploying #{path}") if verbose

  data_sources = options[:data_sources] || []
  data = {
    process: {
      name: deploy_name,
      path: path,
      dataSources: data_sources,
      type: 'RUBY'
    }
  }

  save(data, options)
end
deploy_simple_process(path, options = { client: GoodData.client, project: GoodData.project }) click to toggle source
# File lib/gooddata/models/process.rb, line 105
def deploy_simple_process(path, options = { client: GoodData.client, project: GoodData.project })
  client, project = GoodData.get_client_and_project(options)

  fail 'Path is not specified' unless path

  path = Pathname(path) || fail('Path is not a valid pathname')
  files_to_exclude = options[:files_to_exclude].nil? ? [] : options[:files_to_exclude].map { |pname| Pathname(pname) }

  type = options[:type] || 'GRAPH'
  deploy_name = options[:name] || "Process of #{path} script"
  fail ArgumentError, 'options[:name] can not be nil or empty!' if deploy_name.nil? || deploy_name.empty?

  verbose = options[:verbose] || false
  GoodData.logger.info("Deploying #{path}") if verbose

  deployed_path = Process.upload_package(path, files_to_exclude, client: client, project: project)
  data_sources = options[:data_sources] || []
  data = {
    :process => {
      :name => deploy_name,
      :path => "/uploads/#{File.basename(deployed_path)}",
      :type => type,
      :dataSources => data_sources
    }
  }

  save(data, options)
end
new(data) click to toggle source
# File lib/gooddata/models/process.rb, line 256
def initialize(data)
  @data = data
end
upload_package(path, files_to_exclude, opts = { :client => GoodData.connection }) click to toggle source
# File lib/gooddata/models/process.rb, line 80
def upload_package(path, files_to_exclude, opts = { :client => GoodData.connection })
  GoodData.get_client_and_project(opts)
  zip_and_upload(path, files_to_exclude, opts)
end
with_deploy(dir, options = {}, &block) click to toggle source
# File lib/gooddata/models/process.rb, line 60
def with_deploy(dir, options = {}, &block)
  _client, project = GoodData.get_client_and_project(options)

  GoodData.with_project(project) do
    params = options[:params].nil? ? [] : [options[:params]]
    if block
      begin
        res = GoodData::Process.deploy(dir, options.merge(:files_to_exclude => params))
        block.call(res)
      rescue StandardError => e
        GoodData.logger.error(e.inspect)
      ensure
        res.delete if res
      end
    else
      GoodData::Process.deploy(dir, options.merge(:files_to_exclude => params))
    end
  end
end

Private Class Methods

save(data, options = { client: GoodData.client, project: GoodData.project }) click to toggle source
# File lib/gooddata/models/process.rb, line 200
def save(data, options = { client: GoodData.client, project: GoodData.project })
  client, project = GoodData.get_client_and_project(options)
  process_id = options[:process_id]
  res =
    if process_id.nil?
      client.post("/gdc/projects/#{project.pid}/dataload/processes", data)
    else
      client.put("/gdc/projects/#{project.pid}/dataload/processes/#{process_id}", data)
    end
  res = JSON.parse(client.poll_on_code(res['asyncTask']['links']['poll'], options.merge(process: false))) if res.keys.first == 'asyncTask'

  client.create(Process, res, project: project)
end
with_zip(opts = {}) { |zipfile| ... } click to toggle source
# File lib/gooddata/models/process.rb, line 214
def with_zip(opts = {})
  client = opts[:client]
  temp = Tempfile.new(['deploy-graph-archive', '.zip'])
  zip_filename = temp.path

  temp.close!
  Zip::File.open(zip_filename, Zip::File::CREATE) do |zipfile|
    yield zipfile
  end
  client.upload_to_user_webdav(zip_filename, opts)
  zip_filename
end
zip_and_upload(path, files_to_exclude, opts = {}) click to toggle source
# File lib/gooddata/models/process.rb, line 227
def zip_and_upload(path, files_to_exclude, opts = {})
  client = opts[:client]
  GoodData.logger.info('Creating package for upload')
  if !path.directory? && (path.extname == '.grf' || path.extname == '.rb')
    with_zip(opts) do |zipfile|
      zipfile.add(File.basename(path), path)
    end
  elsif !path.directory?
    # this branch expects a zipped file. Since the filename on webdav is by default
    # equal to the filename of a local file. I happened often that the name clashed
    # if ran in parallel. Create a randomized name to mitigate that
    randomized_filename = (0...16).map { (rand(65..90)).chr }.join
    client.upload_to_user_webdav(path, { filename: randomized_filename }.merge(opts))
    randomized_filename
  else
    with_zip(opts) do |zipfile|
      files_to_upload = Dir[File.join(path, '**', '**')].reject { |f| files_to_exclude.include?(Pathname(path) + f) }
      GoodData.logger.info("Uploading #{files_to_upload.count} files.")
      files_to_upload.each do |file|
        file_pathname = Pathname.new(file)
        file_relative_pathname = file_pathname.relative_path_from(Pathname.new(path))
        zipfile.add(file_relative_pathname, file)
      end
    end
  end
end

Public Instance Methods

add_v2_component?() click to toggle source

Determines whether the process is an ADDv2 component. @return [Bool] True if the process is an ADDv2 component.

# File lib/gooddata/models/process.rb, line 339
def add_v2_component?
  process['component'] && process['component']['name'] == 'gdc-data-distribution'
end
component() click to toggle source
# File lib/gooddata/models/process.rb, line 329
def component
  process['component']
end
create_manual_schedule(options = {}) click to toggle source
# File lib/gooddata/models/process.rb, line 347
def create_manual_schedule(options = {})
  create_schedule(nil, nil, options)
end
create_notification_rule(opts = {}) click to toggle source
# File lib/gooddata/models/process.rb, line 383
def create_notification_rule(opts = {})
  NotificationRule.create(opts.merge(project: project, process: self, client: client))
end
create_schedule(cron, executable, options = {}) click to toggle source
# File lib/gooddata/models/process.rb, line 351
def create_schedule(cron, executable, options = {})
  project.create_schedule(process_id, cron, executable, options.merge(client: client, project: project))
end
data_sources() click to toggle source
# File lib/gooddata/models/process.rb, line 333
def data_sources
  process['dataSources']
end
delete() click to toggle source
# File lib/gooddata/models/process.rb, line 260
def delete
  client.delete(uri)
end
deploy(path, options = {}) click to toggle source

Redeploy existing process.

@param path [String] Path to ZIP archive or to a directory containing files that should be ZIPed @option options [String] :files_to_exclude @option options [String] :process_id (‘nobody’) From address @option options [String] :type (‘GRAPH’) Type of process - GRAPH or RUBY @option options [String] :name Readable name of the process @option options [Boolean] :verbose (false) Switch on verbose mode for detailed logging

# File lib/gooddata/models/process.rb, line 272
def deploy(path, options = {})
  Process.deploy(path, { client: client, process_id: process_id, :project => project, :name => name, :type => type, :data_sources => data_sources }.merge(options))
end
download() click to toggle source

Downloads the process from S3 in a zipped form.

@return [IO] The stream of data that represents a zipped deployed process.

# File lib/gooddata/models/process.rb, line 279
def download
  link = links['source']
  client.connection.refresh_token
  client.get(link, process: false) { |_, _, result| RestClient.get(result.to_hash['location'].first) }
end
executables() click to toggle source
# File lib/gooddata/models/process.rb, line 321
def executables
  process['executables']
end
execute(executable, options = {}) click to toggle source
# File lib/gooddata/models/process.rb, line 355
def execute(executable, options = {})
  result = start_execution(executable, options)
  begin
    client.poll_on_code(result['executionTask']['links']['poll'], options)
  rescue RestClient::RequestFailed => e
    raise(e)
  ensure
    result = client.get(result['executionTask']['links']['detail'])
    fail "Runing process failed. You can look at a log here #{result['executionDetail']['logFileName']}" if result['executionDetail']['status'] == 'ERROR'
  end
  client.create(GoodData::ExecutionDetail, result, client: client, project: project)
end
graphs() click to toggle source
# File lib/gooddata/models/process.rb, line 317
def graphs
  process['graphs']
end
name() click to toggle source
# File lib/gooddata/models/process.rb, line 289
def name
  process['name']
end
notification_rules() click to toggle source
# File lib/gooddata/models/process.rb, line 379
def notification_rules
  NotificationRule.all(project: project, process: self, client: client)
end
obj_id() click to toggle source
# File lib/gooddata/models/process.rb, line 307
def obj_id
  uri.split('/').last
end
Also aliased as: process_id
path() click to toggle source
# File lib/gooddata/models/process.rb, line 325
def path
  process['path']
end
process() click to toggle source
# File lib/gooddata/models/process.rb, line 285
def process
  data['process']
end
process_id()
Alias for: obj_id
schedules() click to toggle source
# File lib/gooddata/models/process.rb, line 343
def schedules
  project.schedules.select { |schedule| schedule.process_id == obj_id }
end
start_execution(executable, options = {}) click to toggle source
# File lib/gooddata/models/process.rb, line 368
def start_execution(executable, options = {})
  params = options[:params] || {}
  hidden_params = options[:hidden_params] || {}
  client.post(executions_link,
              :execution => {
                :graph => executable.to_s,
                :params => GoodData::Helpers.encode_public_params(params),
                :hiddenParams => GoodData::Helpers.encode_hidden_params(hidden_params)
              })
end
type() click to toggle source
# File lib/gooddata/models/process.rb, line 293
def type
  process['type'].downcase.to_sym
end
uri()
Alias for: link