Fix sending resource body to server.
[arvados.git] / sdk / cli / bin / arv
index 947d58e9acc705eaedd9da00e09e5e3d15d55fbf..4db95c846f982b368655f45f1eb0e8597c98d270 100755 (executable)
@@ -10,6 +10,26 @@ if RUBY_VERSION < '1.9.3' then
   EOS
 end
 
+# read authentication data from ~/.arvados if present
+lineno = 0
+config_file = File.expand_path('~/.arvados')
+if File.exist? config_file then
+  File.open(config_file, 'r').each do |line|
+    lineno = lineno + 1
+    # skip comments
+    if line.match('^\s*#') then
+      next
+    end
+    var, val = line.chomp.split('=', 2)
+    # allow environment settings to override config files.
+    if var and val
+      ENV[var] ||= val
+    else
+      warn "#{config_file}: #{lineno}: could not parse `#{line}'"
+    end
+  end
+end
+
 case ARGV[0]
 when 'keep'
   ARGV.shift
@@ -40,6 +60,9 @@ when 'pipeline'
       "(see arv-run-pipeline-instance --help for details)\n"
   end
   abort
+when 'tag'
+  ARGV.shift
+  exec `which arv-tag`.strip, *ARGV
 end
 
 ENV['ARVADOS_API_VERSION'] ||= 'v1'
@@ -51,6 +74,7 @@ ARVADOS_API_HOST and ARVADOS_API_TOKEN need to be defined as environment variabl
 end
 
 begin
+  require 'curb'
   require 'rubygems'
   require 'google/api_client'
   require 'json'
@@ -59,12 +83,13 @@ begin
   require 'andand'
   require 'oj'
   require 'active_support/inflector'
+  require 'yaml'
 rescue LoadError
   abort <<-EOS
 
 Please install all required gems: 
 
-  gem install google-api-client json trollop andand oj activesupport
+  gem install activesupport andand curb google-api-client json oj trollop
 
   EOS
 end
@@ -176,6 +201,7 @@ def parse_arguments(discovery_document)
     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"
     stop_on resource_types
   end
   
@@ -214,12 +240,20 @@ def parse_arguments(discovery_document)
       if body_object["required"] == false
         is_required = false
       end
-      opt resource.to_sym, "#{resource} (request body)", required: is_required, type: :string
+      opt resource.to_sym, "#{resource} (request body)", {
+        required: is_required,
+        type: :string
+      }
+      discovered_params[resource.to_sym] = body_object
     end
   end
+
   discovered_params.each do |k,v|
+    k = k.to_sym
     if ['object', 'array'].index(v["type"]) and method_opts.has_key? k
-      method_opts[k] = JSON.parse method_opts[k]
+      if method_opts[k].andand.match /^\//
+        method_opts[k] = File.open method_opts[k], 'rb' do |f| f.read end
+      end
     end
   end
   return resource, method, method_opts, global_opts, ARGV
@@ -241,16 +275,44 @@ request_parameters = {}.merge(method_opts)
 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 = {}
 end
-request_body[:api_token] = ENV['ARVADOS_API_TOKEN']
-result = client.execute(:api_method => eval(api_method),
-                        :parameters => request_parameters,
-                        :body => request_body,
-                        :authenticated => false)
+
+case api_method
+when
+  'arvados.users.event_stream',
+  'arvados.jobs.log_stream',
+  'arvados.jobs.log_tail_follow'
+
+  # Special case for methods that respond with data streams rather
+  # than JSON (TODO: use the discovery document instead of a static
+  # list of methods)
+  uri_s = eval(api_method).generate_uri(request_parameters)
+  Curl::Easy.perform(uri_s) do |curl|
+    curl.headers['Accept'] = 'text/plain'
+    curl.headers['Authorization'] = "OAuth2 #{ENV['ARVADOS_API_TOKEN']}"
+    if ENV['ARVADOS_API_HOST_INSECURE']
+      curl.ssl_verify_peer = false 
+      curl.ssl_verify_host = false
+    end
+    if global_opts[:verbose]
+      curl.on_header { |data| $stderr.write data }
+    end
+    curl.on_body { |data| $stdout.write data }
+  end
+  exit 0
+else
+  request_body[:api_token] = ENV['ARVADOS_API_TOKEN']
+  request_body[:_profile] = true
+  result = client.execute(:api_method => eval(api_method),
+                          :parameters => request_parameters,
+                          :body => request_body,
+                          :authenticated => false)
+end
+
 begin
   results = JSON.parse result.body
 rescue JSON::ParserError => e
@@ -263,6 +325,8 @@ end
 
 if global_opts[:human] or global_opts[:pretty] then
   puts Oj.dump(results, :indent => 1)
+elsif global_opts[:yaml] then
+  puts results.to_yaml
 elsif global_opts[:json] then
   puts Oj.dump(results)
 elsif results["items"] and results["kind"].match /list$/i