return @discovery_documents["#{api}:#{version}"] ||=
begin
# fetch new API discovery doc if stale
- cached_doc = File.expand_path '~/.cache/arvados/discovery_uri.json'
- if not File.exist?(cached_doc) or (Time.now - File.mtime(cached_doc)) > 86400
+ cached_doc = File.expand_path '~/.cache/arvados/discovery_uri.json' rescue nil
+
+ if cached_doc.nil? or not File.exist?(cached_doc) or (Time.now - File.mtime(cached_doc)) > 86400
response = self.execute!(:http_method => :get,
:uri => self.discovery_uri(api, version),
:authenticated => false)
- FileUtils.makedirs(File.dirname cached_doc)
- File.open(cached_doc, 'w') do |f|
- f.puts response.body
+
+ begin
+ FileUtils.makedirs(File.dirname cached_doc)
+ File.open(cached_doc, 'w') do |f|
+ f.puts response.body
+ end
+ rescue
+ return JSON.load response.body
end
end
def init_config
# read authentication data from arvados configuration file if present
lineno = 0
- config_file = File.expand_path('~/.config/arvados/settings.conf')
- if File.exist? config_file then
+ config_file = File.expand_path('~/.config/arvados/settings.conf') rescue nil
+ if not config_file.nil? and File.exist? config_file then
File.open(config_file, 'r').each do |line|
lineno = lineno + 1
# skip comments
end
abort
when 'pipeline'
- exec `which arv-run-pipeline-instance`.strip, *remaining_opts
+ sub = remaining_opts.shift
+ if sub == 'run'
+ exec `which arv-run-pipeline-instance`.strip, *remaining_opts
+ else
+ puts "Usage: arv pipeline [method] [--parameters]\n"
+ puts "Use 'arv pipeline [method] --help' to get more information about specific methods.\n\n"
+ puts "Available methods: run"
+ end
+ abort
when 'tag'
exec `which arv-tag`.strip, *remaining_opts
when 'ws'
end
end
+def arv_edit_save_tmp tmp
+ FileUtils::cp tmp.path, tmp.path + ".saved"
+ puts "Saved contents to " + tmp.path + ".saved"
+end
+
def arv_edit client, arvados, global_opts, remaining_opts
- n = remaining_opts.shift
- if n.nil? or n == "-h" or n == "--help"
+ uuid = remaining_opts.shift
+ if uuid.nil? or uuid == "-h" or uuid == "--help"
puts head_banner
puts "Usage: arv edit [uuid] [fields...]\n\n"
- puts "Fetchs the specified Arvados object, select the specified fields, and\n"
+ puts "Fetch the specified Arvados object, select the specified fields, \n"
puts "open an interactive text editor on a text representation (json or\n"
- puts "yaml, use --format) and then updates the object. Will use 'nano'\n"
+ puts "yaml, use --format) and then update the object. Will use 'nano'\n"
puts "by default, customize with the EDITOR or VISUAL environment variable.\n"
exit 255
end
# determine controller
- m = /([a-z0-9]{5})-([a-z0-9]{5})-([a-z0-9]{15})/.match n
+ m = /([a-z0-9]{5})-([a-z0-9]{5})-([a-z0-9]{15})/.match uuid
if !m
- abort puts "#{n} does not appear to be an arvados uuid"
+ if /^[a-f0-9]{32}/.match uuid
+ abort "Arvados collections are not editable."
+ else
+ abort "#{n} does not appear to be an Arvados uuid"
+ end
end
rsc = nil
api_method = 'arvados.' + rsc + '.get'
result = client.execute(:api_method => eval(api_method),
- :parameters => {"uuid" => n},
+ :parameters => {"uuid" => uuid},
:authenticated => false,
:headers => {
authorization: 'OAuth2 '+ENV['ARVADOS_API_TOKEN']
require 'tempfile'
- tmp = Tempfile.new([n, "." + global_opts[:format]])
+ tmp = Tempfile.new([uuid, "." + global_opts[:format]])
tmp.write(content)
tmp.close
- pid = Process::fork
- if pid.nil?
- editor ||= ENV["VISUAL"]
- editor ||= ENV["EDITOR"]
- editor ||= "nano"
- exec editor, tmp.path
- else
- Process.wait pid
- end
+ need_edit = true
+
+ while need_edit
+ pid = Process::fork
+ if pid.nil?
+ editor ||= ENV["VISUAL"]
+ editor ||= ENV["EDITOR"]
+ editor ||= "nano"
+ exec editor, tmp.path
+ else
+ Process.wait pid
+ end
- if $?.exitstatus == 0
- tmp.open
- newcontent = tmp.read()
+ if $?.exitstatus == 0
+ tmp.open
+ newcontent = tmp.read()
- newobj = {}
- case global_opts[:format]
- when 'json'
- newobj = Oj.load(newcontent)
- when 'yaml'
- newobj = YAML.load(newcontent)
+ newobj = {}
+ begin
+ case global_opts[:format]
+ when 'json'
+ newobj = Oj.load(newcontent)
+ when 'yaml'
+ newobj = YAML.load(newcontent)
+ end
+ need_edit = false
+ rescue Exception => e
+ puts "Parse error! " + e.to_s
+ n = 1
+ newcontent.each_line do |line|
+ puts "#{n.to_s.rjust 4} #{line}"
+ n += 1
+ end
+ puts "\nTry again (y/n)? "
+ yn = "X"
+ while not ["y", "Y", "n", "N"].include?(yn)
+ yn = $stdin.read 1
+ end
+ if yn == 'n' or yn == 'N'
+ arv_edit_save_tmp tmp
+ abort
+ end
+ end
+ else
+ puts "Editor exited with status #{$?.exitstatus}"
+ exit $?.exitstatus
end
- tmp.close
- tmp.unlink
+ end
+ begin
if newobj != results
api_method = 'arvados.' + rsc + '.update'
- result = client.execute(:api_method => eval(api_method),
- :parameters => {"uuid" => n, rsc.singularize => Oj.dump(newobj)},
- :authenticated => false,
- :headers => {
- authorization: 'OAuth2 '+ENV['ARVADOS_API_TOKEN']
- })
+ dumped = Oj.dump(newobj)
+
+ begin
+ result = client.execute(:api_method => eval(api_method),
+ :parameters => {"uuid" => uuid},
+ :body => { rsc.singularize => dumped },
+ :authenticated => false,
+ :headers => {
+ authorization: 'OAuth2 '+ENV['ARVADOS_API_TOKEN']
+ })
+ rescue Exception => e
+ puts "Error communicating with server, error was #{e}"
+ puts "Update body was:"
+ puts dumped
+ arv_edit_save_tmp tmp
+ abort
+ end
begin
results = JSON.parse result.body
if result.response.status != 200
puts "Update failed. Server responded #{result.response.status}: #{results['errors']} "
+ puts "Update body was:"
+ puts dumped
+ arv_edit_save_tmp tmp
+ abort
end
else
puts "Object is unchanged, did not update."
end
+ ensure
+ tmp.close(true)
end
exit 0
resource = ARGV.shift
if not subcommands.include? resource
- if global_opts[:resources] or not resource_types.include?(resource)
+ if not resource_types.include?(resource)
+ puts "Resource or subcommand '#{resource}' is not recognized.\n\n" if !resource.nil?
help_resources(option_parser, discovery_document, resource)
end