#
# Ward Vandewege <ward@clinicalfuture.com>
+require 'fileutils'
+
if RUBY_VERSION < '1.9.3' then
abort <<-EOS
#{$0.gsub(/^\.\//,'')} requires Ruby version 1.9.3 or higher.
EOS
end
-# read authentication data from ~/.config/arvados if present
+# read authentication data from arvados configuration file if present
lineno = 0
-config_file = File.expand_path('~/.config/arvados')
+config_file = File.expand_path('~/.config/arvados/settings.conf')
if File.exist? config_file then
File.open(config_file, 'r').each do |line|
lineno = lineno + 1
when 'keep'
ARGV.shift
@sub = ARGV.shift
- if ['get', 'put'].index @sub then
+ if ['get', 'put', 'ls', 'normalize'].index @sub then
# Native Arvados
exec `which arv-#{@sub}`.strip, *ARGV
- elsif ['ls', 'less', 'check'].index @sub then
+ elsif ['less', 'check'].index @sub then
# wh* shims
exec `which wh#{@sub}`.strip, *ARGV
else
class Google::APIClient
def discovery_document(api, version)
- api = api.to_s
- return @discovery_documents["#{api}:#{version}"] ||= (begin
- response = self.execute!(
- :http_method => :get,
- :uri => self.discovery_uri(api, version),
- :authenticated => false
- )
- response.body.class == String ? JSON.parse(response.body) : response.body
- end)
+ api = api.to_s
+ 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
+ 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
+ end
+ end
+
+ File.open(cached_doc) { |f| JSON.load f }
+ end
end
end
discovery_document["resources"][resource.pluralize]["methods"].
each do |k,v|
description = ''
- description = ' ' + v["description"] if v.include?("description")
+ if v.include? "description"
+ # add only the first line of the discovery doc description
+ description = ' ' + v["description"].split("\n").first.chomp
+ end
banner += " #{sprintf("%20s",k)}#{description}\n"
end
banner += "\n"
banner += "\n\n"
discovery_document["resources"].each do |k,v|
description = ''
- if discovery_document["schemas"].include?(k.singularize.capitalize) and
- discovery_document["schemas"][k.singularize.capitalize].include?('description') then
- description = ' ' + discovery_document["schemas"][k.singularize.capitalize]["description"]
+ resource_info = discovery_document["schemas"][k.singularize.capitalize]
+ if resource_info and resource_info.include?('description')
+ # add only the first line of the discovery doc description
+ description = ' ' + resource_info["description"].split("\n").first.chomp
end
banner += " #{sprintf("%30s",k.singularize)}#{description}\n"
end
def parse_arguments(discovery_document)
resource_types = Array.new()
- resource_types << '--help'
discovery_document["resources"].each do |k,v|
resource_types << k.singularize
end
global_opts = Trollop::options do
- banner "arvados cli client"
+ version __FILE__
+ banner "arv: the Arvados CLI tool"
opt :dry_run, "Don't actually do anything", :short => "-n"
- opt :verbose, "Print some things on stderr", :short => "-v"
- opt :uuid, "Return the UUIDs of the objects in the response, one per line (default)", :short => nil
- opt :json, "Return the entire response received from the API server, as a JSON object", :short => "-j"
- opt :human, "Return the response received from the API server, as a JSON object with whitespace added for human consumption", :short => "-h"
- opt :pretty, "Synonym of --human", :short => nil
- opt :yaml, "Return the response received from the API server, in YAML format", :short => "-y"
+ opt :verbose, "Print some things on stderr"
+ opt :format,
+ "Set the output format. Must be one of json (default), yaml or uuid.",
+ :type => :string,
+ :default => 'json'
+ opt :short, "Return only UUIDs (equivalent to --format=uuid)"
+ opt :resources, "Display list of resources known to this Arvados instance."
+ conflicts :short, :format
stop_on resource_types
end
-
+
+ unless %w(json yaml uuid).include?(global_opts[:format])
+ $stderr.puts "#{$0}: --format must be one of json, yaml or uuid."
+ $stderr.puts "Use #{$0} --help for more information."
+ abort
+ end
+
+ if global_opts[:short]
+ global_opts[:format] = 'uuid'
+ end
+
resource = ARGV.shift
- if resource == '--help' or not resource_types.include?(resource)
+ if global_opts[:resources] or not resource_types.include?(resource)
help_resources(discovery_document, resource)
end
required: is_required,
type: :string
}
- discovered_params[resource.to_sym] = body_object
end
end
resource_body = request_parameters.delete(resource_schema.to_sym)
if resource_body
request_body = {
- resource_schema => JSON.parse(resource_body)
+ resource_schema => resource_body
}
else
request_body = {}
abort "Error: #{results["errors"][0]}"
end
-if global_opts[:human] or global_opts[:pretty] then
+case global_opts[:format]
+when 'json'
puts Oj.dump(results, :indent => 1)
-elsif global_opts[:yaml] then
+when 'yaml'
puts results.to_yaml
-elsif global_opts[:json] then
- puts Oj.dump(results)
-elsif results["items"] and results["kind"].match /list$/i
- results['items'].each do |i| puts i['uuid'] end
-elsif results['uuid'].nil?
- abort("Response did not include a uuid:\n" +
- Oj.dump(results, :indent => 1) +
- "\n")
else
- puts results['uuid']
+ if results["items"] and results["kind"].match /list$/i
+ results['items'].each do |i| puts i['uuid'] end
+ elsif results['uuid'].nil?
+ abort("Response did not include a uuid:\n" +
+ Oj.dump(results, :indent => 1) +
+ "\n")
+ else
+ puts results['uuid']
+ end
end
+
+