iij-dag 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +18 -0
 - data/Gemfile +16 -0
 - data/LICENSE.txt +174 -0
 - data/Rakefile +27 -0
 - data/bin/dag +7 -0
 - data/iij-dag.gemspec +34 -0
 - data/lib/dag/cli.rb +17 -0
 - data/lib/dag/cli/base.rb +128 -0
 - data/lib/dag/cli/command.rb +83 -0
 - data/lib/dag/cli/command/import.rb +30 -0
 - data/lib/dag/cli/command/query.rb +14 -0
 - data/lib/dag/cli/sub_command.rb +18 -0
 - data/lib/dag/cli/sub_command/bucket.rb +90 -0
 - data/lib/dag/cli/sub_command/cluster.rb +187 -0
 - data/lib/dag/cli/sub_command/db.rb +38 -0
 - data/lib/dag/cli/sub_command/job.rb +341 -0
 - data/lib/dag/cli/sub_command/table.rb +168 -0
 - data/lib/dag/cli/utils.rb +7 -0
 - data/lib/dag/cli/utils/number_to_human.rb +23 -0
 - data/lib/dag/cli/utils/terminal_table.rb +10 -0
 - data/lib/dag/cli/utils/time_format.rb +8 -0
 - data/lib/dag/cli/version.rb +5 -0
 - metadata +221 -0
 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dag
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Import
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(client, db, table, files, format, params)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @client = client
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @db = db
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @table = table
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @files = files
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @params = params
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @format = format
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def execute
         
     | 
| 
      
 14 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 15 
     | 
    
         
            +
                      @client.database(@db)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    rescue Dag::Client::DatabaseNotFound
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @client.create_database(@db)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 21 
     | 
    
         
            +
                      @client.database(@db).table(@table)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    rescue Dag::Client::TableNotFound
         
     | 
| 
      
 23 
     | 
    
         
            +
                      @client.create_table(@db, @table, format: @format)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    @client.import(@db, @table, @files, @params)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dag
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 3 
     | 
    
         
            +
                class SubCommand < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include Dag::CLI::Utils::TimeFormat
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def self.banner(task, namespace = false, subcommand = true)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    super
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  desc 'help [COMMAND]', 'Describe available commands or one specific command'
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def help(command = nil, subcommand = false)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    super
         
     | 
| 
      
 13 
     | 
    
         
            +
                    cmd = self.class.name.split('::').last.downcase
         
     | 
| 
      
 14 
     | 
    
         
            +
                    shell.say "Type 'dag #{cmd} help [COMMAND]' for more information on a specific command"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'pathname'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Dag
         
     | 
| 
      
 6 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Bucket < SubCommand
         
     | 
| 
      
 8 
     | 
    
         
            +
                  desc 'list ([BUCKET])', 'show bucket/object list'
         
     | 
| 
      
 9 
     | 
    
         
            +
                  option :prefix, type: :string, aliases: '-p', desc: "prefix filter", default: nil
         
     | 
| 
      
 10 
     | 
    
         
            +
                  option :delimiter, type: :string, aliases: '-d', desc: "object delimiter", default: nil
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def list(bucket = nil)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    fields = [:name]
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    unless bucket
         
     | 
| 
      
 15 
     | 
    
         
            +
                      rows = handle_api_failure do
         
     | 
| 
      
 16 
     | 
    
         
            +
                        client.buckets
         
     | 
| 
      
 17 
     | 
    
         
            +
                      end
         
     | 
| 
      
 18 
     | 
    
         
            +
                    else
         
     | 
| 
      
 19 
     | 
    
         
            +
                      rows = handle_api_failure do
         
     | 
| 
      
 20 
     | 
    
         
            +
                        bucket = client.buckets[bucket]
         
     | 
| 
      
 21 
     | 
    
         
            +
                        bucket.objects.where(prefix: options[:prefix], delimiter: options[:delimiter])
         
     | 
| 
      
 22 
     | 
    
         
            +
                      end
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 26 
     | 
    
         
            +
                      rows.each do |row|
         
     | 
| 
      
 27 
     | 
    
         
            +
                        puts row.name
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  desc 'read [BUCKET] [OBJECT]', 'read object'
         
     | 
| 
      
 33 
     | 
    
         
            +
                  def read(bucket, object)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    rows = handle_api_failure do
         
     | 
| 
      
 35 
     | 
    
         
            +
                      bucket = client.buckets[bucket]
         
     | 
| 
      
 36 
     | 
    
         
            +
                      bucket.objects[object].read
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
                    print rows
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  desc 'create [BUCKET]', 'create bucket'
         
     | 
| 
      
 42 
     | 
    
         
            +
                  def create(bucket)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    rows = handle_api_failure do
         
     | 
| 
      
 44 
     | 
    
         
            +
                      client.create_bucket(bucket)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
                    say_status("Create bucket", rows.name)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  desc 'delete [BUCKET] ([OBJECT])', 'delete bucket or object'
         
     | 
| 
      
 50 
     | 
    
         
            +
                  def delete(bucket, *objects)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 52 
     | 
    
         
            +
                      if objects.empty?
         
     | 
| 
      
 53 
     | 
    
         
            +
                        # for bucket
         
     | 
| 
      
 54 
     | 
    
         
            +
                        client.delete_bucket(bucket)
         
     | 
| 
      
 55 
     | 
    
         
            +
                        say_status("Delete bucket", bucket)
         
     | 
| 
      
 56 
     | 
    
         
            +
                      else
         
     | 
| 
      
 57 
     | 
    
         
            +
                        # for objects
         
     | 
| 
      
 58 
     | 
    
         
            +
                        th = []
         
     | 
| 
      
 59 
     | 
    
         
            +
                        objects.each do |object|
         
     | 
| 
      
 60 
     | 
    
         
            +
                          th << Thread.new do
         
     | 
| 
      
 61 
     | 
    
         
            +
                            client.delete_object(bucket, object)
         
     | 
| 
      
 62 
     | 
    
         
            +
                            say_status("Delete object", File.join(bucket, object))
         
     | 
| 
      
 63 
     | 
    
         
            +
                          end
         
     | 
| 
      
 64 
     | 
    
         
            +
                        end
         
     | 
| 
      
 65 
     | 
    
         
            +
                        th.map(&:join)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      end
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  desc 'write [BUCKET] [OBJECT]', 'write object / string or file path'
         
     | 
| 
      
 71 
     | 
    
         
            +
                  option :data, type: :string, aliases: '-d', desc: "string or file path", required: true
         
     | 
| 
      
 72 
     | 
    
         
            +
                  option :multipart, type: :boolean, aliases: '-m', desc: "multipart upload"
         
     | 
| 
      
 73 
     | 
    
         
            +
                  option :multipart_jobs, type: :numeric, aliases: '-j', desc: "multipart upload jobs"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  option :multipart_splitsz, type: :numeric, aliases: '-s', desc: "multipart upload split size"
         
     | 
| 
      
 75 
     | 
    
         
            +
                  def write(bucket, object)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    params = {}
         
     | 
| 
      
 77 
     | 
    
         
            +
                    params.merge!(multipart: true) if options[:multipart]
         
     | 
| 
      
 78 
     | 
    
         
            +
                    params.merge!(jobs: options[:multipart_jobs]) if options[:multipart_jobs]
         
     | 
| 
      
 79 
     | 
    
         
            +
                    params.merge!(splitsz: options[:multipart_splitsz]) if options[:multipart_splitsz]
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                    data = File.exist?(options[:data]) ? Pathname.new(options[:data]) : options[:data]
         
     | 
| 
      
 82 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 83 
     | 
    
         
            +
                      obj = client.buckets[bucket].objects[object]
         
     | 
| 
      
 84 
     | 
    
         
            +
                      obj.write(data, params)
         
     | 
| 
      
 85 
     | 
    
         
            +
                      say_status("Write object", File.join(bucket, object))
         
     | 
| 
      
 86 
     | 
    
         
            +
                    end
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,187 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            module Dag
         
     | 
| 
      
 3 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 4 
     | 
    
         
            +
                class Cluster < SubCommand
         
     | 
| 
      
 5 
     | 
    
         
            +
                  include Dag::CLI::Utils::NumberToHuman
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  class NotClusterFound < StandardError; end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  desc 'attach ([CLUSTER])', 'Attach cluster'
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def attach(cluster = nil)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    if cluster
         
     | 
| 
      
 12 
     | 
    
         
            +
                      attached_cluster = handle_api_failure do
         
     | 
| 
      
 13 
     | 
    
         
            +
                        open_client{ cluster }.cluster
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      local_store { |db| db[:cluster] = cluster }
         
     | 
| 
      
 17 
     | 
    
         
            +
                      say_status "Attach cluster", attached_cluster.name
         
     | 
| 
      
 18 
     | 
    
         
            +
                    else
         
     | 
| 
      
 19 
     | 
    
         
            +
                      cluster = local_store { |db| db[:cluster] }
         
     | 
| 
      
 20 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 21 
     | 
    
         
            +
                        raise NotClusterFound if cluster.nil?
         
     | 
| 
      
 22 
     | 
    
         
            +
                        say_status "Attached cluster", cluster
         
     | 
| 
      
 23 
     | 
    
         
            +
                      rescue NotClusterFound
         
     | 
| 
      
 24 
     | 
    
         
            +
                        abort "Please attach to the cluster\nType 'dag cluster attach [CLUSTER]'"
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  desc 'detach', 'Detach cluster'
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def detach
         
     | 
| 
      
 31 
     | 
    
         
            +
                    attached_cluster = ''
         
     | 
| 
      
 32 
     | 
    
         
            +
                    local_store do |db|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      attached_cluster = db[:cluster]
         
     | 
| 
      
 34 
     | 
    
         
            +
                      raise NotClusterFound if attached_cluster.nil?
         
     | 
| 
      
 35 
     | 
    
         
            +
                      db[:cluster] = nil
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                    say_status "Detach cluster", attached_cluster
         
     | 
| 
      
 38 
     | 
    
         
            +
                  rescue NotClusterFound
         
     | 
| 
      
 39 
     | 
    
         
            +
                    abort "Please attach to the cluster\nType 'dag attach [CLUSTER]'"
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  desc 'list', 'show cluster list'
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def list
         
     | 
| 
      
 44 
     | 
    
         
            +
                    headers = %w(# name status type instances)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    rows = []
         
     | 
| 
      
 46 
     | 
    
         
            +
                    attach_cluster = local_store { |db| db[:cluster] }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 49 
     | 
    
         
            +
                      client.clusters.each do |cluster|
         
     | 
| 
      
 50 
     | 
    
         
            +
                        total_container = cluster.instances.lazy.map{|c| c["quantity"] }.inject(:+)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        cluster_row = [cluster.name, cluster.status, cluster.type, total_container || 0]
         
     | 
| 
      
 52 
     | 
    
         
            +
                        rows << if attach_cluster == cluster.name
         
     | 
| 
      
 53 
     | 
    
         
            +
                          cluster_row.unshift('*')
         
     | 
| 
      
 54 
     | 
    
         
            +
                        else
         
     | 
| 
      
 55 
     | 
    
         
            +
                          cluster_row.unshift(nil)
         
     | 
| 
      
 56 
     | 
    
         
            +
                        end
         
     | 
| 
      
 57 
     | 
    
         
            +
                      end
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    terminal_table(rows, headers: headers, max_width: Float::INFINITY)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  desc 'info', 'Cluster instance info id/dfs_used/non_dfs_used/capacity/grade'
         
     | 
| 
      
 64 
     | 
    
         
            +
                  def info
         
     | 
| 
      
 65 
     | 
    
         
            +
                    headers = %w(instance_id grade dfs_used non_dfs_used capacity)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    rows = []
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    cluster = handle_api_failure do
         
     | 
| 
      
 69 
     | 
    
         
            +
                      open_client.cluster
         
     | 
| 
      
 70 
     | 
    
         
            +
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    statistics = cluster.statistics
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    unless statistics
         
     | 
| 
      
 74 
     | 
    
         
            +
                      return say_status(
         
     | 
| 
      
 75 
     | 
    
         
            +
                          "InvalidClusterState",
         
     | 
| 
      
 76 
     | 
    
         
            +
                          "Cluster status is invalid: #{cluster.status}",
         
     | 
| 
      
 77 
     | 
    
         
            +
                          :red
         
     | 
| 
      
 78 
     | 
    
         
            +
                      )
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                    statistics.instances.each do |instance|
         
     | 
| 
      
 82 
     | 
    
         
            +
                      rows << [
         
     | 
| 
      
 83 
     | 
    
         
            +
                          instance.instance_id,
         
     | 
| 
      
 84 
     | 
    
         
            +
                          instance.grade,
         
     | 
| 
      
 85 
     | 
    
         
            +
                          number_to_human(instance.disk.dfs_used),
         
     | 
| 
      
 86 
     | 
    
         
            +
                          number_to_human(instance.disk.non_dfs_used),
         
     | 
| 
      
 87 
     | 
    
         
            +
                          number_to_human(instance.disk.capacity)
         
     | 
| 
      
 88 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                    puts "Cluster: #{cluster.name}"
         
     | 
| 
      
 92 
     | 
    
         
            +
                    terminal_table(rows, headers: headers) 
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  desc 'restart', 'restart cluster'
         
     | 
| 
      
 96 
     | 
    
         
            +
                  option :force, type: :boolean, aliases: '-f', default: false, desc: 'cluster force restart'
         
     | 
| 
      
 97 
     | 
    
         
            +
                  option :type,  type: :string,  aliases: '-t', default: nil, desc: 'change cluster type'
         
     | 
| 
      
 98 
     | 
    
         
            +
                  option :wait,  type: :boolean, aliases: '-w', default: false, desc: 'wait until normal cluster status'
         
     | 
| 
      
 99 
     | 
    
         
            +
                  option :assumeyes,   type: :boolean, aliases: '-y', desc: 'assume that the answer to any question which would be asked is yes'
         
     | 
| 
      
 100 
     | 
    
         
            +
                  def restart
         
     | 
| 
      
 101 
     | 
    
         
            +
                    unless options[:assumeyes]
         
     | 
| 
      
 102 
     | 
    
         
            +
                      loop do
         
     | 
| 
      
 103 
     | 
    
         
            +
                        ans = ask 'Is this ok [y/N]:'
         
     | 
| 
      
 104 
     | 
    
         
            +
                        case ans
         
     | 
| 
      
 105 
     | 
    
         
            +
                          when 'y'
         
     | 
| 
      
 106 
     | 
    
         
            +
                            break
         
     | 
| 
      
 107 
     | 
    
         
            +
                          when 'N'
         
     | 
| 
      
 108 
     | 
    
         
            +
                            exit
         
     | 
| 
      
 109 
     | 
    
         
            +
                        end
         
     | 
| 
      
 110 
     | 
    
         
            +
                      end
         
     | 
| 
      
 111 
     | 
    
         
            +
                    end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                    headers = %w(name type force)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    rows = []
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                    cluster = handle_api_failure do
         
     | 
| 
      
 117 
     | 
    
         
            +
                      open_client.cluster
         
     | 
| 
      
 118 
     | 
    
         
            +
                    end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                    options[:type] ||= cluster.type
         
     | 
| 
      
 121 
     | 
    
         
            +
                    params = { force: options[:force], type: options[:type] }
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 124 
     | 
    
         
            +
                      cluster.restart(params)
         
     | 
| 
      
 125 
     | 
    
         
            +
                    end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                    rows << [cluster.name, params[:type], params[:force]]
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                    terminal_table(rows, headers: headers)
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                    if options[:wait]
         
     | 
| 
      
 132 
     | 
    
         
            +
                      puts
         
     | 
| 
      
 133 
     | 
    
         
            +
                      puts 'wait cluster ready...'
         
     | 
| 
      
 134 
     | 
    
         
            +
                      wait_ready
         
     | 
| 
      
 135 
     | 
    
         
            +
                    end
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                  desc 'wait_ready', 'wait cluster ready'
         
     | 
| 
      
 139 
     | 
    
         
            +
                  def wait_ready
         
     | 
| 
      
 140 
     | 
    
         
            +
                    pretime = Time.now
         
     | 
| 
      
 141 
     | 
    
         
            +
                    prestate = ""
         
     | 
| 
      
 142 
     | 
    
         
            +
                    state = []
         
     | 
| 
      
 143 
     | 
    
         
            +
                    state_num = 0
         
     | 
| 
      
 144 
     | 
    
         
            +
                    while true do
         
     | 
| 
      
 145 
     | 
    
         
            +
                      cluster = handle_api_failure do
         
     | 
| 
      
 146 
     | 
    
         
            +
                        open_client.cluster
         
     | 
| 
      
 147 
     | 
    
         
            +
                      end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                      st = cluster.status
         
     | 
| 
      
 150 
     | 
    
         
            +
                      now = Proc.new { "#{st}(#{(Time.now-pretime).round}s)" }
         
     | 
| 
      
 151 
     | 
    
         
            +
                      fiber = Fiber.new {|state| Fiber.yield state }
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                      if prestate != st
         
     | 
| 
      
 154 
     | 
    
         
            +
                        prestate = st
         
     | 
| 
      
 155 
     | 
    
         
            +
                        pretime = Time.now
         
     | 
| 
      
 156 
     | 
    
         
            +
                        state << now.call
         
     | 
| 
      
 157 
     | 
    
         
            +
                        state_num += 1
         
     | 
| 
      
 158 
     | 
    
         
            +
                      end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                      state[state_num-1] = now.call
         
     | 
| 
      
 161 
     | 
    
         
            +
                      print "#{fiber.resume(state*' ')}\r"
         
     | 
| 
      
 162 
     | 
    
         
            +
                      $stdout.flush
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                      if %w(norm failed ptfailed error).include? st
         
     | 
| 
      
 165 
     | 
    
         
            +
                        print "\n"
         
     | 
| 
      
 166 
     | 
    
         
            +
                        break
         
     | 
| 
      
 167 
     | 
    
         
            +
                      end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                      sleep 1
         
     | 
| 
      
 170 
     | 
    
         
            +
                    end
         
     | 
| 
      
 171 
     | 
    
         
            +
                  end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                  desc 'log [OUTPUT_PATH]', 'export cluster log'
         
     | 
| 
      
 174 
     | 
    
         
            +
                  option :compress, type: :boolean, aliases: '-c', default: false
         
     | 
| 
      
 175 
     | 
    
         
            +
                  def log(output_log_path)
         
     | 
| 
      
 176 
     | 
    
         
            +
                    params = {
         
     | 
| 
      
 177 
     | 
    
         
            +
                        compress: options[:compress],
         
     | 
| 
      
 178 
     | 
    
         
            +
                        output_log_path: output_log_path
         
     | 
| 
      
 179 
     | 
    
         
            +
                    }
         
     | 
| 
      
 180 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 181 
     | 
    
         
            +
                      cluster = open_client.cluster
         
     | 
| 
      
 182 
     | 
    
         
            +
                      cluster.export_log(params)
         
     | 
| 
      
 183 
     | 
    
         
            +
                    end
         
     | 
| 
      
 184 
     | 
    
         
            +
                  end
         
     | 
| 
      
 185 
     | 
    
         
            +
                end
         
     | 
| 
      
 186 
     | 
    
         
            +
              end
         
     | 
| 
      
 187 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            module Dag
         
     | 
| 
      
 3 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 4 
     | 
    
         
            +
                class Db < SubCommand
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  desc 'list', 'Show database list'
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def list
         
     | 
| 
      
 8 
     | 
    
         
            +
                    fields = %w(name)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    rows = handle_api_failure { open_client.databases }
         
     | 
| 
      
 10 
     | 
    
         
            +
                    terminal_table(rows, fields: fields)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  desc 'create [DATABASE]', 'Create database'
         
     | 
| 
      
 14 
     | 
    
         
            +
                  def create(db_name)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    database = handle_api_failure do
         
     | 
| 
      
 16 
     | 
    
         
            +
                      open_client.create_database(db_name)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    say_status "Create Database", database.name
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  desc 'delete [DATABASE]', 'Delete database'
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def delete(db_name)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    db = ''
         
     | 
| 
      
 25 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 26 
     | 
    
         
            +
                      db = open_client.database(db_name)
         
     | 
| 
      
 27 
     | 
    
         
            +
                      db.delete if db
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    if db
         
     | 
| 
      
 31 
     | 
    
         
            +
                      say_status "Delete Database", db_name
         
     | 
| 
      
 32 
     | 
    
         
            +
                    else
         
     | 
| 
      
 33 
     | 
    
         
            +
                      say_status "Unknown Database", db_name, :red
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,341 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'ruby-progressbar'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'csv'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'anbt-sql-formatter/formatter'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module Dag
         
     | 
| 
      
 8 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 9 
     | 
    
         
            +
                class Job < SubCommand
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  desc 'list', 'Jobs list'
         
     | 
| 
      
 12 
     | 
    
         
            +
                  option :order, type: :string, aliases: '-o', desc: "list order [asc|desc]"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  option :filter, type: :hash, aliases: '-f', desc: "list filter key [status|type|cluster_name|label|cluster_rebooted]"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  option :limit, type: :numeric, aliases: '-n', desc: "The location is number lines"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  def list
         
     | 
| 
      
 16 
     | 
    
         
            +
                    headers = %w(id status start_at type cluster query)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    rows = []
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    if options[:filter] && cluster_rebooted = options[:filter]['cluster_rebooted']
         
     | 
| 
      
 20 
     | 
    
         
            +
                      options[:filter]['cluster_rebooted'] = case cluster_rebooted
         
     | 
| 
      
 21 
     | 
    
         
            +
                        when "true"
         
     | 
| 
      
 22 
     | 
    
         
            +
                          true
         
     | 
| 
      
 23 
     | 
    
         
            +
                        when "false"
         
     | 
| 
      
 24 
     | 
    
         
            +
                          false
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 29 
     | 
    
         
            +
                      jobs = client.jobs.where(cluster_name: open_client.cluster_name)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                      if options[:filter]
         
     | 
| 
      
 32 
     | 
    
         
            +
                        jobs = jobs.where(options[:filter].symbolize_keys)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                      if options[:limit]
         
     | 
| 
      
 36 
     | 
    
         
            +
                        jobs = jobs.limit(options[:limit])
         
     | 
| 
      
 37 
     | 
    
         
            +
                      end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                      iterator = :each
         
     | 
| 
      
 40 
     | 
    
         
            +
                      order = if options[:order]
         
     | 
| 
      
 41 
     | 
    
         
            +
                                options[:order]
         
     | 
| 
      
 42 
     | 
    
         
            +
                              else
         
     | 
| 
      
 43 
     | 
    
         
            +
                                if [:limit]
         
     | 
| 
      
 44 
     | 
    
         
            +
                                  iterator = :reverse_each
         
     | 
| 
      
 45 
     | 
    
         
            +
                                  'desc'
         
     | 
| 
      
 46 
     | 
    
         
            +
                                else
         
     | 
| 
      
 47 
     | 
    
         
            +
                                  'asc'
         
     | 
| 
      
 48 
     | 
    
         
            +
                                end
         
     | 
| 
      
 49 
     | 
    
         
            +
                              end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                      jobs.order(order).send(iterator) do |job|
         
     | 
| 
      
 52 
     | 
    
         
            +
                        row = [ job.id ]
         
     | 
| 
      
 53 
     | 
    
         
            +
                        row += [ job.status ]
         
     | 
| 
      
 54 
     | 
    
         
            +
                        row += [ time_format(job.start_at) ]
         
     | 
| 
      
 55 
     | 
    
         
            +
                        row += [ job.type ]
         
     | 
| 
      
 56 
     | 
    
         
            +
                        row += [ job.cluster ]
         
     | 
| 
      
 57 
     | 
    
         
            +
                        row += [ job.query ]
         
     | 
| 
      
 58 
     | 
    
         
            +
                        rows << row
         
     | 
| 
      
 59 
     | 
    
         
            +
                      end
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    terminal_table(rows, headers: headers)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  desc 'info [JOB_ID]', 'Job info'
         
     | 
| 
      
 66 
     | 
    
         
            +
                  def info(job_id)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    headers = ["item", "info"]
         
     | 
| 
      
 68 
     | 
    
         
            +
                    rows = []
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    job = handle_api_failure do
         
     | 
| 
      
 71 
     | 
    
         
            +
                      client.job(job_id)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    rows << ["id", job.id]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    rows << ["status", job.status]
         
     | 
| 
      
 76 
     | 
    
         
            +
                    rows << ["start_at", time_format(job.start_at)]
         
     | 
| 
      
 77 
     | 
    
         
            +
                    rows << ["type", job.type]
         
     | 
| 
      
 78 
     | 
    
         
            +
                    rows << ["dsl", job.dsl]
         
     | 
| 
      
 79 
     | 
    
         
            +
                    rows << ["cluster", job.cluster]
         
     | 
| 
      
 80 
     | 
    
         
            +
                    rows << ["cluster_rebooted", job.cluster_rebooted]
         
     | 
| 
      
 81 
     | 
    
         
            +
                    rows << ["label", job.label]
         
     | 
| 
      
 82 
     | 
    
         
            +
                    rows << ["stage", job.stage]
         
     | 
| 
      
 83 
     | 
    
         
            +
                    rows << ["progress", job.progress]
         
     | 
| 
      
 84 
     | 
    
         
            +
                    rows << ["access_key_id", job.access_key_id]
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                    case job.dsl
         
     | 
| 
      
 87 
     | 
    
         
            +
                      when "hive"
         
     | 
| 
      
 88 
     | 
    
         
            +
                        rows << ["output_format", job.output_format]
         
     | 
| 
      
 89 
     | 
    
         
            +
                        rows << ["output_resource_path", job.output_resource_path]
         
     | 
| 
      
 90 
     | 
    
         
            +
                        query = sql_format(job.query).split("\n")
         
     | 
| 
      
 91 
     | 
    
         
            +
                        query.each_with_index do |line, i|
         
     | 
| 
      
 92 
     | 
    
         
            +
                          rows << ['', line]
         
     | 
| 
      
 93 
     | 
    
         
            +
                          rows.last[0] = 'query' if i == 0
         
     | 
| 
      
 94 
     | 
    
         
            +
                        end
         
     | 
| 
      
 95 
     | 
    
         
            +
                      when "mapreduce"
         
     | 
| 
      
 96 
     | 
    
         
            +
                        rows << ["job_id", job.job_id]
         
     | 
| 
      
 97 
     | 
    
         
            +
                        rows << ["schema", job.schema]
         
     | 
| 
      
 98 
     | 
    
         
            +
                        rows << ["input_object_keys", job.input_object_keys]
         
     | 
| 
      
 99 
     | 
    
         
            +
                        rows << ["input_format", job.input_format]
         
     | 
| 
      
 100 
     | 
    
         
            +
                        rows << ["output_database", job.output_database]
         
     | 
| 
      
 101 
     | 
    
         
            +
                        rows << ["output_table", job.output_table]
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                    # vertical, unicode, tab, markdown, simple
         
     | 
| 
      
 105 
     | 
    
         
            +
                    terminal_table(rows, headers: headers, max_width: Float::INFINITY)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  desc 'reuse [JOB_ID]', 'reuse job'
         
     | 
| 
      
 109 
     | 
    
         
            +
                  option :output, type: :string, aliases: '-o', desc: 'new output storage path'
         
     | 
| 
      
 110 
     | 
    
         
            +
                  option :format, type: :string, aliases: '-f', desc: 'new output format [csv/tsv]'
         
     | 
| 
      
 111 
     | 
    
         
            +
                  option :label, type: :string, aliases: '-l', desc: 'new job label'
         
     | 
| 
      
 112 
     | 
    
         
            +
                  option :query, type: :string, aliases: '-q', desc: 'new query'
         
     | 
| 
      
 113 
     | 
    
         
            +
                  option :wait, type: :boolean, aliases: '-w', desc: 'wait job finish'
         
     | 
| 
      
 114 
     | 
    
         
            +
                  def reuse(job_id)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    reuse_job = handle_api_failure do
         
     | 
| 
      
 116 
     | 
    
         
            +
                      client.job(job_id)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                    if reuse_job.type == "select"
         
     | 
| 
      
 120 
     | 
    
         
            +
                      query_string = options[:query]
         
     | 
| 
      
 121 
     | 
    
         
            +
                      if query_string
         
     | 
| 
      
 122 
     | 
    
         
            +
                        if File.exists? query_string
         
     | 
| 
      
 123 
     | 
    
         
            +
                          query_string = open(query_string).read
         
     | 
| 
      
 124 
     | 
    
         
            +
                          puts "Query: #{query_string}"
         
     | 
| 
      
 125 
     | 
    
         
            +
                        end
         
     | 
| 
      
 126 
     | 
    
         
            +
                      else
         
     | 
| 
      
 127 
     | 
    
         
            +
                        query_string = reuse_job.query
         
     | 
| 
      
 128 
     | 
    
         
            +
                      end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                      output_format = options[:format]
         
     | 
| 
      
 131 
     | 
    
         
            +
                      unless output_format
         
     | 
| 
      
 132 
     | 
    
         
            +
                        output_format = reuse_job.output_format
         
     | 
| 
      
 133 
     | 
    
         
            +
                      end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                      output_resource_path = options[:output]
         
     | 
| 
      
 136 
     | 
    
         
            +
                      unless output_resource_path
         
     | 
| 
      
 137 
     | 
    
         
            +
                        output_resource_path = reuse_job.output_resource_path
         
     | 
| 
      
 138 
     | 
    
         
            +
                      end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                      label = options[:label]
         
     | 
| 
      
 141 
     | 
    
         
            +
                      unless label
         
     | 
| 
      
 142 
     | 
    
         
            +
                        label = reuse_job.label
         
     | 
| 
      
 143 
     | 
    
         
            +
                      end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                      params = {
         
     | 
| 
      
 146 
     | 
    
         
            +
                          query: query_string,
         
     | 
| 
      
 147 
     | 
    
         
            +
                          output_format: output_format,
         
     | 
| 
      
 148 
     | 
    
         
            +
                          output_resource_path: output_resource_path,
         
     | 
| 
      
 149 
     | 
    
         
            +
                          label: label
         
     | 
| 
      
 150 
     | 
    
         
            +
                      }
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                      query = Query.new(open_client, params)
         
     | 
| 
      
 153 
     | 
    
         
            +
                      job = handle_api_failure { query.execute }
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                      say_status "accepted job", "job_id: #{job.id}"
         
     | 
| 
      
 156 
     | 
    
         
            +
                      if options[:wait]
         
     | 
| 
      
 157 
     | 
    
         
            +
                        CLI::Command.start(["job", "log", job.id.to_s, "-t"])
         
     | 
| 
      
 158 
     | 
    
         
            +
                        CLI::Command.start(["job", "result", job.id.to_s])
         
     | 
| 
      
 159 
     | 
    
         
            +
                      end
         
     | 
| 
      
 160 
     | 
    
         
            +
                    else
         
     | 
| 
      
 161 
     | 
    
         
            +
                      say_status "invalid job type", "job_type: #{reuse_job.type}"
         
     | 
| 
      
 162 
     | 
    
         
            +
                      exit 1
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                  desc 'log [JOB_ID]', 'show job log'
         
     | 
| 
      
 167 
     | 
    
         
            +
                  option :tail, type: :boolean, aliases: '-t', desc: 'tail -f'
         
     | 
| 
      
 168 
     | 
    
         
            +
                  def log(job_id)
         
     | 
| 
      
 169 
     | 
    
         
            +
                    if options[:tail]
         
     | 
| 
      
 170 
     | 
    
         
            +
                      mark=nil
         
     | 
| 
      
 171 
     | 
    
         
            +
                      while true
         
     | 
| 
      
 172 
     | 
    
         
            +
                        jst, log = handle_api_failure {
         
     | 
| 
      
 173 
     | 
    
         
            +
                          j = client.job(job_id)
         
     | 
| 
      
 174 
     | 
    
         
            +
                          [j.running?, j.log]
         
     | 
| 
      
 175 
     | 
    
         
            +
                        }
         
     | 
| 
      
 176 
     | 
    
         
            +
                        lines = log.split("\n")
         
     | 
| 
      
 177 
     | 
    
         
            +
                        if mark
         
     | 
| 
      
 178 
     | 
    
         
            +
                          n = lines.rindex(mark)
         
     | 
| 
      
 179 
     | 
    
         
            +
                          lines = lines[(n+1)..-1] if n
         
     | 
| 
      
 180 
     | 
    
         
            +
                        end
         
     | 
| 
      
 181 
     | 
    
         
            +
                        unless lines.empty?
         
     | 
| 
      
 182 
     | 
    
         
            +
                          mark=lines[-1]
         
     | 
| 
      
 183 
     | 
    
         
            +
                          puts lines.join("\n")
         
     | 
| 
      
 184 
     | 
    
         
            +
                        end
         
     | 
| 
      
 185 
     | 
    
         
            +
                        break unless jst
         
     | 
| 
      
 186 
     | 
    
         
            +
                        sleep 1
         
     | 
| 
      
 187 
     | 
    
         
            +
                      end
         
     | 
| 
      
 188 
     | 
    
         
            +
                    else
         
     | 
| 
      
 189 
     | 
    
         
            +
                      log = handle_api_failure do
         
     | 
| 
      
 190 
     | 
    
         
            +
                        client.job(job_id).log
         
     | 
| 
      
 191 
     | 
    
         
            +
                      end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                      puts log
         
     | 
| 
      
 194 
     | 
    
         
            +
                    end
         
     | 
| 
      
 195 
     | 
    
         
            +
                  end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                  desc 'result [JOB_ID]', 'Create download url'
         
     | 
| 
      
 198 
     | 
    
         
            +
                  option :format, type: :string, aliases: '-f', desc: 'output format [csv|tsv|table|url|time]', default: "table"
         
     | 
| 
      
 199 
     | 
    
         
            +
                  def result(job_id)
         
     | 
| 
      
 200 
     | 
    
         
            +
                    if options[:format] == "url"
         
     | 
| 
      
 201 
     | 
    
         
            +
                      download_url = handle_api_failure do
         
     | 
| 
      
 202 
     | 
    
         
            +
                        client.job(job_id).download_urls
         
     | 
| 
      
 203 
     | 
    
         
            +
                      end
         
     | 
| 
      
 204 
     | 
    
         
            +
                      puts download_url
         
     | 
| 
      
 205 
     | 
    
         
            +
                      return
         
     | 
| 
      
 206 
     | 
    
         
            +
                    end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                    unless job_id.include? "/"
         
     | 
| 
      
 209 
     | 
    
         
            +
                      job = handle_api_failure do
         
     | 
| 
      
 210 
     | 
    
         
            +
                        client.job(job_id)
         
     | 
| 
      
 211 
     | 
    
         
            +
                      end
         
     | 
| 
      
 212 
     | 
    
         
            +
                      target = job.output_resource_path
         
     | 
| 
      
 213 
     | 
    
         
            +
                    else
         
     | 
| 
      
 214 
     | 
    
         
            +
                      target = job_id
         
     | 
| 
      
 215 
     | 
    
         
            +
                    end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                    unless target
         
     | 
| 
      
 218 
     | 
    
         
            +
                      if job.try(:type) == 'split'
         
     | 
| 
      
 219 
     | 
    
         
            +
                        say_status 'ERROR', 'Invalid job type', :red
         
     | 
| 
      
 220 
     | 
    
         
            +
                      else
         
     | 
| 
      
 221 
     | 
    
         
            +
                        say_status 'ERROR', 'Invalid job_id or dag://bucket/prefix/', :red
         
     | 
| 
      
 222 
     | 
    
         
            +
                      end
         
     | 
| 
      
 223 
     | 
    
         
            +
                      exit 1
         
     | 
| 
      
 224 
     | 
    
         
            +
                    end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                    unless job && job.finished?
         
     | 
| 
      
 227 
     | 
    
         
            +
                      say_status 'ERROR', "Job is not finished (status=#{job.status})", :red
         
     | 
| 
      
 228 
     | 
    
         
            +
                      return
         
     | 
| 
      
 229 
     | 
    
         
            +
                    end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                    uri = URI.parse(target)
         
     | 
| 
      
 232 
     | 
    
         
            +
                    bucket = uri.host
         
     | 
| 
      
 233 
     | 
    
         
            +
                    prefix = uri.path[1..-1]
         
     | 
| 
      
 234 
     | 
    
         
            +
                    bucket = client.buckets[bucket]
         
     | 
| 
      
 235 
     | 
    
         
            +
                    rsm = handle_api_failure do
         
     | 
| 
      
 236 
     | 
    
         
            +
                      bucket.objects[File.join(prefix, ".resultsetmetadata")].read
         
     | 
| 
      
 237 
     | 
    
         
            +
                    end
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
                    if rsm.headers['Last-Modified'].present?
         
     | 
| 
      
 240 
     | 
    
         
            +
                      finishedat = Time.parse(rsm.headers['Last-Modified'].first)
         
     | 
| 
      
 241 
     | 
    
         
            +
                    end
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                    if %w(table time).include? options[:format]
         
     | 
| 
      
 244 
     | 
    
         
            +
                      h = []
         
     | 
| 
      
 245 
     | 
    
         
            +
                      h << "job start at #{time_format(job.start_at)}" if job
         
     | 
| 
      
 246 
     | 
    
         
            +
                      h << "finished #{time_format(finishedat)}" if finishedat
         
     | 
| 
      
 247 
     | 
    
         
            +
                      h << "#{(finishedat-job.start_at).to_i} seconds." if job && finishedat
         
     | 
| 
      
 248 
     | 
    
         
            +
                      puts h.join(", ")
         
     | 
| 
      
 249 
     | 
    
         
            +
                      return if options[:format]=="time"
         
     | 
| 
      
 250 
     | 
    
         
            +
                    end
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                    field_separator = ","
         
     | 
| 
      
 253 
     | 
    
         
            +
                    field_separator = "\t" if job.output_format == "tsv"
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
                    hdr = Oj.load(rsm)
         
     | 
| 
      
 256 
     | 
    
         
            +
                    hdrs=[]
         
     | 
| 
      
 257 
     | 
    
         
            +
                    hdr["columns"].each{|e| hdrs[e["position"].to_i-1] = e["name"] }
         
     | 
| 
      
 258 
     | 
    
         
            +
                    rows = handle_api_failure do
         
     | 
| 
      
 259 
     | 
    
         
            +
                      bucket.objects.where(prefix: prefix)
         
     | 
| 
      
 260 
     | 
    
         
            +
                       .select{|s| s.name.include? "/0" }
         
     | 
| 
      
 261 
     | 
    
         
            +
                       .map{|e| CSV.parse(bucket.objects[e.name].read, col_sep: field_separator) }
         
     | 
| 
      
 262 
     | 
    
         
            +
                    end
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
                    rows.each{|obj|
         
     | 
| 
      
 265 
     | 
    
         
            +
                      case options[:format]
         
     | 
| 
      
 266 
     | 
    
         
            +
                      when 'csv'
         
     | 
| 
      
 267 
     | 
    
         
            +
                        puts hdrs.join(",")
         
     | 
| 
      
 268 
     | 
    
         
            +
                        puts obj.map{|m| m.join(",") }.join("\n")
         
     | 
| 
      
 269 
     | 
    
         
            +
                      when 'tsv'
         
     | 
| 
      
 270 
     | 
    
         
            +
                        puts hdrs.join("\t")
         
     | 
| 
      
 271 
     | 
    
         
            +
                        puts obj.map{|m| m.join("\t") }.join("\n")
         
     | 
| 
      
 272 
     | 
    
         
            +
                      else
         
     | 
| 
      
 273 
     | 
    
         
            +
                        terminal_table(obj, headers: hdrs)
         
     | 
| 
      
 274 
     | 
    
         
            +
                      end
         
     | 
| 
      
 275 
     | 
    
         
            +
                    }
         
     | 
| 
      
 276 
     | 
    
         
            +
                  end
         
     | 
| 
      
 277 
     | 
    
         
            +
             
     | 
| 
      
 278 
     | 
    
         
            +
                  desc 'kill! [JOB_ID]', 'Stop job'
         
     | 
| 
      
 279 
     | 
    
         
            +
                  def kill!(job_id)
         
     | 
| 
      
 280 
     | 
    
         
            +
                    handle_api_failure do
         
     | 
| 
      
 281 
     | 
    
         
            +
                      client.job(job_id).kill
         
     | 
| 
      
 282 
     | 
    
         
            +
                    end
         
     | 
| 
      
 283 
     | 
    
         
            +
             
     | 
| 
      
 284 
     | 
    
         
            +
                    say_status("Cancelling job", job_id)
         
     | 
| 
      
 285 
     | 
    
         
            +
                  end
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
                  desc 'progress [JOB_ID]', 'Show Progress Bar'
         
     | 
| 
      
 288 
     | 
    
         
            +
                  def progress(job_id=nil)
         
     | 
| 
      
 289 
     | 
    
         
            +
                    if job_id
         
     | 
| 
      
 290 
     | 
    
         
            +
                      jobs = [job_id]
         
     | 
| 
      
 291 
     | 
    
         
            +
                    else
         
     | 
| 
      
 292 
     | 
    
         
            +
                      jobs = handle_api_failure{
         
     | 
| 
      
 293 
     | 
    
         
            +
                        client.jobs.select{|j| j.running? }.map{|j| j.id }
         
     | 
| 
      
 294 
     | 
    
         
            +
                      }
         
     | 
| 
      
 295 
     | 
    
         
            +
                    end
         
     | 
| 
      
 296 
     | 
    
         
            +
                    return unless jobs.length==1
         
     | 
| 
      
 297 
     | 
    
         
            +
                    progress_bar = ProgressBar.create(total: 100, format: '%t %a <%B> %p%% %e', autofinish: false)
         
     | 
| 
      
 298 
     | 
    
         
            +
                    stage = nil
         
     | 
| 
      
 299 
     | 
    
         
            +
                    while true
         
     | 
| 
      
 300 
     | 
    
         
            +
                      job = handle_api_failure{ client.job(jobs[0]) }
         
     | 
| 
      
 301 
     | 
    
         
            +
                      if ! job.running?
         
     | 
| 
      
 302 
     | 
    
         
            +
                        progress_bar.finish
         
     | 
| 
      
 303 
     | 
    
         
            +
                        puts "#{job.status}"
         
     | 
| 
      
 304 
     | 
    
         
            +
                        break
         
     | 
| 
      
 305 
     | 
    
         
            +
                      end
         
     | 
| 
      
 306 
     | 
    
         
            +
                      if job.stage && stage!=job.stage
         
     | 
| 
      
 307 
     | 
    
         
            +
                        progress_bar.finish if stage
         
     | 
| 
      
 308 
     | 
    
         
            +
                        progress_bar = ProgressBar.create(title: "Stage-#{job.stage}/Job-#{jobs[0]}", total: 100, format: '%t %a <%B> %p%% %e', autofinish: false)
         
     | 
| 
      
 309 
     | 
    
         
            +
                        stage = job.stage
         
     | 
| 
      
 310 
     | 
    
         
            +
                      end
         
     | 
| 
      
 311 
     | 
    
         
            +
                      progress_bar.progress = job.progress.to_f if job.progress && stage == job.stage
         
     | 
| 
      
 312 
     | 
    
         
            +
                      sleep 1
         
     | 
| 
      
 313 
     | 
    
         
            +
                    end
         
     | 
| 
      
 314 
     | 
    
         
            +
                  end
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
      
 316 
     | 
    
         
            +
                  desc 'wait [JOB_ID]', 'wait job'
         
     | 
| 
      
 317 
     | 
    
         
            +
                  def wait(job_id=nil)
         
     | 
| 
      
 318 
     | 
    
         
            +
                    while true
         
     | 
| 
      
 319 
     | 
    
         
            +
                      if job_id
         
     | 
| 
      
 320 
     | 
    
         
            +
                        job = handle_api_failure{ client.job(job_id) }
         
     | 
| 
      
 321 
     | 
    
         
            +
                        break unless job.running?
         
     | 
| 
      
 322 
     | 
    
         
            +
                      else
         
     | 
| 
      
 323 
     | 
    
         
            +
                        jobs = handle_api_failure{
         
     | 
| 
      
 324 
     | 
    
         
            +
                          client.jobs.select{|j| j.running? }
         
     | 
| 
      
 325 
     | 
    
         
            +
                        }
         
     | 
| 
      
 326 
     | 
    
         
            +
                        break if jobs.empty?
         
     | 
| 
      
 327 
     | 
    
         
            +
                      end
         
     | 
| 
      
 328 
     | 
    
         
            +
                      sleep 1
         
     | 
| 
      
 329 
     | 
    
         
            +
                    end
         
     | 
| 
      
 330 
     | 
    
         
            +
                  end
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
      
 332 
     | 
    
         
            +
                  private
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                  def sql_format(query)
         
     | 
| 
      
 335 
     | 
    
         
            +
                    tmp = query.dup
         
     | 
| 
      
 336 
     | 
    
         
            +
                    sql_formatter = AnbtSql::Formatter.new(AnbtSql::Rule.new)
         
     | 
| 
      
 337 
     | 
    
         
            +
                    sql_formatter.format(tmp).to_s
         
     | 
| 
      
 338 
     | 
    
         
            +
                  end
         
     | 
| 
      
 339 
     | 
    
         
            +
                end
         
     | 
| 
      
 340 
     | 
    
         
            +
              end
         
     | 
| 
      
 341 
     | 
    
         
            +
            end
         
     |