Class: RightScraper::Processes::Warden

Inherits:
Object
  • Object
show all
Defined in:
lib/right_scraper/processes/warden.rb

Defined Under Namespace

Classes: LinkError, LinkResult, StateError, WardenError

Constant Summary collapse

DEFAULT_RVM_HOME =
'/usr/local/rvm'
DEFAULT_WARDEN_HOME =
'/opt/warden'
RELATIVE_SCRIPTS_RVM_PATH =
'scripts/rvm'
DEFAULT_RVM_RUBY_VERSION =

TEAL FIX: dynamically discover highest rvm-installed ruby 1.9 build?

'ruby-1.9.3-p448'
WARDEN_SERVICE_SUBDIR_NAME =
'warden'
RELATIVE_WARDEN_SCRIPT_PATH =
'bin/warden'
WARDEN_COMMAND_TIMEOUT =

max seconds to spawn, link, etc.

60
DEFAULT_OPTIONS =
{
  :warden_home      => DEFAULT_WARDEN_HOME,
  :rvm_home         => DEFAULT_RVM_HOME,
  :rvm_ruby_version => DEFAULT_RVM_RUBY_VERSION
}

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Warden

Returns a new instance of Warden.

Raises:



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/right_scraper/processes/warden.rb', line 83

def initialize(options = {})
  options = DEFAULT_OPTIONS.merge(options)
  @warden_home = options[:warden_home]
  @rvm_home = options[:rvm_home]
  unless @rvm_ruby_version = options[:rvm_ruby_version]
    raise ArgumentError.new('options[:rvm_ruby_version] is required')
  end

  # warden paths
  unless @warden_home && ::File.directory?(@warden_home)
    raise ArgumentError.new('options[:warden_home] is required')
  end
  unless @rvm_home && ::File.directory?(@rvm_home)
    raise ArgumentError.new('options[:rvm_home] is required')
  end
  @warden_server_dir = ::File.join(@warden_home, WARDEN_SERVICE_SUBDIR_NAME)
  @bin_warden_path = ::File.join(@warden_server_dir, RELATIVE_WARDEN_SCRIPT_PATH)
  unless File.file?(@bin_warden_path)
    raise StateError, "Warden CLI script cannot be found at #{@bin_warden_path.inspect}"
  end

  # rvm paths
  @scripts_rvm_path = ::File.join(@rvm_home, RELATIVE_SCRIPTS_RVM_PATH)
  unless File.file?(@scripts_rvm_path)
    raise StateError, "RVM setup script cannot be found at #{@scripts_rvm_path.inspect}"
  end

  # build the jail.
  @handle = send('create')['handle']
  raise StateError, 'handle is invalid' unless @handle
end

Instance Method Details

#cleanupObject



167
168
169
170
171
172
173
# File 'lib/right_scraper/processes/warden.rb', line 167

def cleanup
  raise StateError, 'handle is invalid' unless @handle
  lay_to_rest
  send("destroy --handle #{@handle}")
ensure
  @handle = nil
end

#run_command_in_jail(cmds, copy_in = nil, copy_out = nil) ⇒ String

Runs the script given by container-relative path. Optionally copies files in/out before/after script execution.

Parameters

Return

Raise

Parameters:

  • cmds (String|Array)

    to execute

  • copy_in (String|Array) (defaults to: nil)

    file(s) to copy into jail (using same path on both sides) or nil or empty

  • copy_out (Hash) (defaults to: nil)

    files as map of jail source path to host destination path or empty or nil

Returns:

  • (String)

    stdout text

Raises:



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/right_scraper/processes/warden.rb', line 130

def run_command_in_jail(cmds, copy_in = nil, copy_out = nil)
  cmds = Array(cmds)
  raise ArgumentError, 'cmds is required' if cmds.empty?
  raise StateError, 'handle is invalid' unless @handle

  # copy any files in before running commands.
  copy_in = Array(copy_in)
  send_copy_in_cmds(copy_in) if !copy_in.empty?

  # note that appending --privileged will run script as root, but we have
  # no use case for running scripts as root at this time.
  output = []
  cmds.each do |cmd|
    job_id = send("spawn --handle #{@handle} --script #{cmd.inspect}")['job_id']
    link_result = LinkResult.new(send("link --handle #{@handle} --job_id #{job_id}"))
    if link_result.succeeded?
      output << link_result.stdout
    else
      raise LinkError.new('Script failed running in isolation.', link_result)
    end
  end

  # copy any files out after command(s) succeeded.
  if copy_out && !copy_out.empty?
    copy_out_cmds = copy_out.inject([]) do |result, (src_path, dst_path)|
      # create output directories because warden will only copy files.
      parent_dir = ::File.dirname(dst_path)
      ::FileUtils.mkdir_p(parent_dir)
      result << "copy_out --handle #{@handle} --src_path #{src_path.inspect} --dst_path #{dst_path.inspect}"
      result
    end
    send(copy_out_cmds)
  end

  return output.join("\n")
end