td-client 0.8.67 → 0.8.68
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 +4 -4
- data/lib/td/client.rb +12 -2
- data/lib/td/client/api.rb +51 -1040
- data/lib/td/client/api/access_control.rb +62 -0
- data/lib/td/client/api/account.rb +41 -0
- data/lib/td/client/api/bulk_import.rb +154 -0
- data/lib/td/client/api/database.rb +47 -0
- data/lib/td/client/api/export.rb +21 -0
- data/lib/td/client/api/import.rb +31 -0
- data/lib/td/client/api/job.rb +251 -0
- data/lib/td/client/api/partial_delete.rb +21 -0
- data/lib/td/client/api/result.rb +41 -0
- data/lib/td/client/api/schedule.rb +106 -0
- data/lib/td/client/api/server_status.rb +20 -0
- data/lib/td/client/api/table.rb +123 -0
- data/lib/td/client/api/user.rb +117 -0
- data/lib/td/client/api_error.rb +26 -0
- data/lib/td/client/model.rb +7 -5
- data/lib/td/client/version.rb +1 -1
- data/lib/td/core_ext/openssl/ssl/sslcontext/set_params.rb +18 -0
- data/spec/spec_helper.rb +8 -4
- data/spec/td/client/access_control_api_spec.rb +37 -0
- data/spec/td/client/account_api_spec.rb +34 -0
- data/spec/td/client/api_ssl_connection_spec.rb +10 -7
- data/spec/td/client/bulk_import_spec.rb +144 -0
- data/spec/td/client/import_api_spec.rb +73 -0
- data/spec/td/client/job_api_spec.rb +124 -1
- data/spec/td/client/result_api_spec.rb +23 -0
- data/spec/td/client/sched_api_spec.rb +33 -0
- data/spec/td/client/server_status_api_spec.rb +25 -0
- data/spec/td/client/table_api_spec.rb +45 -0
- data/spec/td/client/user_api_spec.rb +118 -0
- data/spec/td/client_sched_spec.rb +54 -0
- metadata +37 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: a6f4ce3a275f3c038d731feb43dda2ec4cc477e5
         | 
| 4 | 
            +
              data.tar.gz: b6affcd7ad8e6430af814d9459cfbabde9ae50f9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3127bd887d7fff303cde39f92932d8d9a263cfb37201e3c299a24e53a3767390a70ce4195fe34ce9003ecd815465a0776e3e094cc1c35d3da37f181bc4273c98
         | 
| 7 | 
            +
              data.tar.gz: d002d279379a09a63c10882503cf09f6d25d7e3d12198281c55e82881d8f1ef5a7e2ca2af3cb66856b89d8056667da7003a5172f91d424e87fba8a1c625ddcdf
         | 
    
        data/lib/td/client.rb
    CHANGED
    
    | @@ -287,8 +287,18 @@ class Client | |
| 287 287 | 
             
              def history(name, from=nil, to=nil)
         | 
| 288 288 | 
             
                result = @api.history(name, from, to)
         | 
| 289 289 | 
             
                result.map {|scheduled_at,job_id,type,status,query,start_at,end_at,result_url,priority,database|
         | 
| 290 | 
            -
                   | 
| 291 | 
            -
             | 
| 290 | 
            +
                  job_param = [job_id, type, query, status,
         | 
| 291 | 
            +
                    nil, nil, # url, debug
         | 
| 292 | 
            +
                    start_at, end_at,
         | 
| 293 | 
            +
                    nil, # cpu_time
         | 
| 294 | 
            +
                    nil, nil, # result_size, result
         | 
| 295 | 
            +
                    result_url,
         | 
| 296 | 
            +
                    nil, # hive_result_schema
         | 
| 297 | 
            +
                    priority,
         | 
| 298 | 
            +
                    nil, # retry_limit
         | 
| 299 | 
            +
                    nil, # TODO org_name
         | 
| 300 | 
            +
                    database]
         | 
| 301 | 
            +
                  ScheduledJob.new(self, scheduled_at, *job_param)
         | 
| 292 302 | 
             
                }
         | 
| 293 303 | 
             
              end
         | 
| 294 304 |  | 
    
        data/lib/td/client/api.rb
    CHANGED
    
    | @@ -1,32 +1,39 @@ | |
| 1 | 
            +
            require 'td/client/api_error'
         | 
| 1 2 | 
             
            require 'td/client/version'
         | 
| 3 | 
            +
            require 'td/client/api/access_control'
         | 
| 4 | 
            +
            require 'td/client/api/account'
         | 
| 5 | 
            +
            require 'td/client/api/bulk_import'
         | 
| 6 | 
            +
            require 'td/client/api/database'
         | 
| 7 | 
            +
            require 'td/client/api/export'
         | 
| 8 | 
            +
            require 'td/client/api/import'
         | 
| 9 | 
            +
            require 'td/client/api/job'
         | 
| 10 | 
            +
            require 'td/client/api/partial_delete'
         | 
| 11 | 
            +
            require 'td/client/api/result'
         | 
| 12 | 
            +
            require 'td/client/api/schedule'
         | 
| 13 | 
            +
            require 'td/client/api/server_status'
         | 
| 14 | 
            +
            require 'td/client/api/table'
         | 
| 15 | 
            +
            require 'td/client/api/user'
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            # For disabling SSLv3 connection in favor of POODLE Attack protection
         | 
| 18 | 
            +
            require 'td/core_ext/openssl/ssl/sslcontext/set_params'
         | 
| 2 19 |  | 
| 3 20 | 
             
            module TreasureData
         | 
| 4 21 |  | 
| 5 | 
            -
            class ParameterValidationError < StandardError
         | 
| 6 | 
            -
            end
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            # Generic API error
         | 
| 9 | 
            -
            class APIError < StandardError
         | 
| 10 | 
            -
            end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            # 401 API errors
         | 
| 13 | 
            -
            class AuthError < APIError
         | 
| 14 | 
            -
            end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
            # 403 API errors, used for database permissions
         | 
| 17 | 
            -
            class ForbiddenError < APIError
         | 
| 18 | 
            -
            end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
            # 409 API errors
         | 
| 21 | 
            -
            class AlreadyExistsError < APIError
         | 
| 22 | 
            -
            end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
            # 404 API errors
         | 
| 25 | 
            -
            class NotFoundError < APIError
         | 
| 26 | 
            -
            end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 22 | 
             
            class API
         | 
| 23 | 
            +
              include API::AccessControl
         | 
| 24 | 
            +
              include API::Account
         | 
| 25 | 
            +
              include API::BulkImport
         | 
| 26 | 
            +
              include API::Database
         | 
| 27 | 
            +
              include API::Export
         | 
| 28 | 
            +
              include API::Import
         | 
| 29 | 
            +
              include API::Job
         | 
| 30 | 
            +
              include API::PartialDelete
         | 
| 31 | 
            +
              include API::Result
         | 
| 32 | 
            +
              include API::Schedule
         | 
| 33 | 
            +
              include API::ServerStatus
         | 
| 34 | 
            +
              include API::Table
         | 
| 35 | 
            +
              include API::User
         | 
| 36 | 
            +
             | 
| 30 37 | 
             
              DEFAULT_ENDPOINT = 'api.treasure-data.com'
         | 
| 31 38 | 
             
              DEFAULT_IMPORT_ENDPOINT = 'api-import.treasure-data.com'
         | 
| 32 39 |  | 
| @@ -42,6 +49,10 @@ class API | |
| 42 49 | 
             
                require 'time'
         | 
| 43 50 | 
             
                #require 'faraday' # faraday doesn't support streaming upload with httpclient yet so now disabled
         | 
| 44 51 | 
             
                require 'httpclient'
         | 
| 52 | 
            +
                require 'zlib'
         | 
| 53 | 
            +
                require 'stringio'
         | 
| 54 | 
            +
                require 'cgi'
         | 
| 55 | 
            +
                require 'msgpack'
         | 
| 45 56 |  | 
| 46 57 | 
             
                @apikey = apikey
         | 
| 47 58 | 
             
                @user_agent = "TD-Client-Ruby: #{TreasureData::Client::VERSION}"
         | 
| @@ -195,1006 +206,17 @@ class API | |
| 195 206 |  | 
| 196 207 | 
             
              # for fluent-plugin-td / td command to check table existence with import onlt user
         | 
| 197 208 | 
             
              def self.create_empty_gz_data
         | 
| 198 | 
            -
                require 'zlib'
         | 
| 199 | 
            -
                require 'stringio'
         | 
| 200 | 
            -
             | 
| 201 209 | 
             
                io = StringIO.new
         | 
| 202 210 | 
             
                Zlib::GzipWriter.new(io).close
         | 
| 203 211 | 
             
                io.string
         | 
| 204 212 | 
             
              end
         | 
| 205 213 |  | 
| 206 | 
            -
              ####
         | 
| 207 | 
            -
              ## Account API
         | 
| 208 | 
            -
              ##
         | 
| 209 | 
            -
             | 
| 210 | 
            -
              def show_account
         | 
| 211 | 
            -
                code, body, res = get("/v3/account/show")
         | 
| 212 | 
            -
                if code != "200"
         | 
| 213 | 
            -
                  raise_error("Show account failed", res)
         | 
| 214 | 
            -
                end
         | 
| 215 | 
            -
                js = checked_json(body, %w[account])
         | 
| 216 | 
            -
                a = js["account"]
         | 
| 217 | 
            -
                account_id = a['id'].to_i
         | 
| 218 | 
            -
                plan = a['plan'].to_i
         | 
| 219 | 
            -
                storage_size = a['storage_size'].to_i
         | 
| 220 | 
            -
                guaranteed_cores = a['guaranteed_cores'].to_i
         | 
| 221 | 
            -
                maximum_cores = a['maximum_cores'].to_i
         | 
| 222 | 
            -
                created_at = a['created_at']
         | 
| 223 | 
            -
                return [account_id, plan, storage_size, guaranteed_cores, maximum_cores, created_at]
         | 
| 224 | 
            -
              end
         | 
| 225 | 
            -
             | 
| 226 | 
            -
              def account_core_utilization(from, to)
         | 
| 227 | 
            -
                params = { }
         | 
| 228 | 
            -
                params['from'] = from.to_s if from
         | 
| 229 | 
            -
                params['to'] = to.to_s if to
         | 
| 230 | 
            -
                code, body, res = get("/v3/account/core_utilization", params)
         | 
| 231 | 
            -
                if code != "200"
         | 
| 232 | 
            -
                  raise_error("Show account failed", res)
         | 
| 233 | 
            -
                end
         | 
| 234 | 
            -
                js = checked_json(body, %w[from to interval history])
         | 
| 235 | 
            -
                from = Time.parse(js['from']).utc
         | 
| 236 | 
            -
                to = Time.parse(js['to']).utc
         | 
| 237 | 
            -
                interval = js['interval'].to_i
         | 
| 238 | 
            -
                history = js['history']
         | 
| 239 | 
            -
                return [from, to, interval, history]
         | 
| 240 | 
            -
              end
         | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
              ####
         | 
| 244 | 
            -
              ## Database API
         | 
| 245 | 
            -
              ##
         | 
| 246 | 
            -
             | 
| 247 | 
            -
              # => [name:String]
         | 
| 248 | 
            -
              def list_databases
         | 
| 249 | 
            -
                code, body, res = get("/v3/database/list")
         | 
| 250 | 
            -
                if code != "200"
         | 
| 251 | 
            -
                  raise_error("List databases failed", res)
         | 
| 252 | 
            -
                end
         | 
| 253 | 
            -
                js = checked_json(body, %w[databases])
         | 
| 254 | 
            -
                result = {}
         | 
| 255 | 
            -
                js["databases"].each {|m|
         | 
| 256 | 
            -
                  name = m['name']
         | 
| 257 | 
            -
                  count = m['count']
         | 
| 258 | 
            -
                  created_at = m['created_at']
         | 
| 259 | 
            -
                  updated_at = m['updated_at']
         | 
| 260 | 
            -
                  permission = m['permission']
         | 
| 261 | 
            -
                  result[name] = [count, created_at, updated_at, nil, permission] # set nil to org for API compatibiilty
         | 
| 262 | 
            -
                }
         | 
| 263 | 
            -
                return result
         | 
| 264 | 
            -
              end
         | 
| 265 | 
            -
             | 
| 266 | 
            -
              # => true
         | 
| 267 | 
            -
              def delete_database(db)
         | 
| 268 | 
            -
                code, body, res = post("/v3/database/delete/#{e db}")
         | 
| 269 | 
            -
                if code != "200"
         | 
| 270 | 
            -
                  raise_error("Delete database failed", res)
         | 
| 271 | 
            -
                end
         | 
| 272 | 
            -
                return true
         | 
| 273 | 
            -
              end
         | 
| 274 | 
            -
             | 
| 275 | 
            -
              # => true
         | 
| 276 | 
            -
              def create_database(db, opts={})
         | 
| 277 | 
            -
                params = opts.dup
         | 
| 278 | 
            -
                code, body, res = post("/v3/database/create/#{e db}", params)
         | 
| 279 | 
            -
                if code != "200"
         | 
| 280 | 
            -
                  raise_error("Create database failed", res)
         | 
| 281 | 
            -
                end
         | 
| 282 | 
            -
                return true
         | 
| 283 | 
            -
              end
         | 
| 284 | 
            -
             | 
| 285 | 
            -
             | 
| 286 | 
            -
              ####
         | 
| 287 | 
            -
              ## Table API
         | 
| 288 | 
            -
              ##
         | 
| 289 | 
            -
             | 
| 290 | 
            -
              # => {name:String => [type:Symbol, count:Integer]}
         | 
| 291 | 
            -
              def list_tables(db)
         | 
| 292 | 
            -
                code, body, res = get("/v3/table/list/#{e db}")
         | 
| 293 | 
            -
                if code != "200"
         | 
| 294 | 
            -
                  raise_error("List tables failed", res)
         | 
| 295 | 
            -
                end
         | 
| 296 | 
            -
                js = checked_json(body, %w[tables])
         | 
| 297 | 
            -
                result = {}
         | 
| 298 | 
            -
                js["tables"].map {|m|
         | 
| 299 | 
            -
                  name = m['name']
         | 
| 300 | 
            -
                  type = (m['type'] || '?').to_sym
         | 
| 301 | 
            -
                  count = (m['count'] || 0).to_i  # TODO?
         | 
| 302 | 
            -
                  created_at = m['created_at']
         | 
| 303 | 
            -
                  updated_at = m['updated_at']
         | 
| 304 | 
            -
                  last_import = m['counter_updated_at']
         | 
| 305 | 
            -
                  last_log_timestamp = m['last_log_timestamp']
         | 
| 306 | 
            -
                  estimated_storage_size = m['estimated_storage_size'].to_i
         | 
| 307 | 
            -
                  schema = JSON.parse(m['schema'] || '[]')
         | 
| 308 | 
            -
                  expire_days = m['expire_days']
         | 
| 309 | 
            -
                  primary_key = m['primary_key']
         | 
| 310 | 
            -
                  primary_key_type = m['primary_key_type']
         | 
| 311 | 
            -
                  result[name] = [type, schema, count, created_at, updated_at, estimated_storage_size, last_import, last_log_timestamp, expire_days, primary_key, primary_key_type]
         | 
| 312 | 
            -
                }
         | 
| 313 | 
            -
                return result
         | 
| 314 | 
            -
              end
         | 
| 315 | 
            -
             | 
| 316 | 
            -
              def create_log_or_item_table(db, table, type)
         | 
| 317 | 
            -
                code, body, res = post("/v3/table/create/#{e db}/#{e table}/#{type}")
         | 
| 318 | 
            -
                if code != "200"
         | 
| 319 | 
            -
                  raise_error("Create #{type} table failed", res)
         | 
| 320 | 
            -
                end
         | 
| 321 | 
            -
                return true
         | 
| 322 | 
            -
              end
         | 
| 323 | 
            -
              private :create_log_or_item_table
         | 
| 324 | 
            -
             | 
| 325 | 
            -
              # => true
         | 
| 326 | 
            -
              def create_log_table(db, table)
         | 
| 327 | 
            -
                create_table(db, table, :log)
         | 
| 328 | 
            -
              end
         | 
| 329 | 
            -
             | 
| 330 | 
            -
              # => true
         | 
| 331 | 
            -
              def create_item_table(db, table, primary_key, primary_key_type)
         | 
| 332 | 
            -
                params = {'primary_key' => primary_key, 'primary_key_type' => primary_key_type}
         | 
| 333 | 
            -
                create_table(db, table, :item, params)
         | 
| 334 | 
            -
              end
         | 
| 335 | 
            -
             | 
| 336 | 
            -
              def create_table(db, table, type, params={})
         | 
| 337 | 
            -
                schema = schema.to_s
         | 
| 338 | 
            -
                code, body, res = post("/v3/table/create/#{e db}/#{e table}/#{type}", params)
         | 
| 339 | 
            -
                if code != "200"
         | 
| 340 | 
            -
                  raise_error("Create #{type} table failed", res)
         | 
| 341 | 
            -
                end
         | 
| 342 | 
            -
                return true
         | 
| 343 | 
            -
              end
         | 
| 344 | 
            -
              private :create_table
         | 
| 345 | 
            -
             | 
| 346 | 
            -
              # => true
         | 
| 347 | 
            -
              def swap_table(db, table1, table2)
         | 
| 348 | 
            -
                code, body, res = post("/v3/table/swap/#{e db}/#{e table1}/#{e table2}")
         | 
| 349 | 
            -
                if code != "200"
         | 
| 350 | 
            -
                  raise_error("Swap tables failed", res)
         | 
| 351 | 
            -
                end
         | 
| 352 | 
            -
                return true
         | 
| 353 | 
            -
              end
         | 
| 354 | 
            -
             | 
| 355 | 
            -
              # => true
         | 
| 356 | 
            -
              def update_schema(db, table, schema_json)
         | 
| 357 | 
            -
                code, body, res = post("/v3/table/update-schema/#{e db}/#{e table}", {'schema'=>schema_json})
         | 
| 358 | 
            -
                if code != "200"
         | 
| 359 | 
            -
                  raise_error("Create schema table failed", res)
         | 
| 360 | 
            -
                end
         | 
| 361 | 
            -
                return true
         | 
| 362 | 
            -
              end
         | 
| 363 | 
            -
             | 
| 364 | 
            -
              def update_expire(db, table, expire_days)
         | 
| 365 | 
            -
                code, body, res = post("/v3/table/update/#{e db}/#{e table}", {'expire_days'=>expire_days})
         | 
| 366 | 
            -
                if code != "200"
         | 
| 367 | 
            -
                  raise_error("Update table expiration failed", res)
         | 
| 368 | 
            -
                end
         | 
| 369 | 
            -
                return true
         | 
| 370 | 
            -
              end
         | 
| 371 | 
            -
             | 
| 372 | 
            -
              # => type:Symbol
         | 
| 373 | 
            -
              def delete_table(db, table)
         | 
| 374 | 
            -
                code, body, res = post("/v3/table/delete/#{e db}/#{e table}")
         | 
| 375 | 
            -
                if code != "200"
         | 
| 376 | 
            -
                  raise_error("Delete table failed", res)
         | 
| 377 | 
            -
                end
         | 
| 378 | 
            -
                js = checked_json(body, %w[])
         | 
| 379 | 
            -
                type = (js['type'] || '?').to_sym
         | 
| 380 | 
            -
                return type
         | 
| 381 | 
            -
              end
         | 
| 382 | 
            -
             | 
| 383 | 
            -
              def tail(db, table, count, to, from, &block)
         | 
| 384 | 
            -
                params = {'format' => 'msgpack'}
         | 
| 385 | 
            -
                params['count'] = count.to_s if count
         | 
| 386 | 
            -
                params['to'] = to.to_s if to
         | 
| 387 | 
            -
                params['from'] = from.to_s if from
         | 
| 388 | 
            -
                code, body, res = get("/v3/table/tail/#{e db}/#{e table}", params)
         | 
| 389 | 
            -
                if code != "200"
         | 
| 390 | 
            -
                  raise_error("Tail table failed", res)
         | 
| 391 | 
            -
                end
         | 
| 392 | 
            -
                require 'msgpack'
         | 
| 393 | 
            -
                if block
         | 
| 394 | 
            -
                  MessagePack::Unpacker.new.feed_each(body, &block)
         | 
| 395 | 
            -
                  nil
         | 
| 396 | 
            -
                else
         | 
| 397 | 
            -
                  result = []
         | 
| 398 | 
            -
                  MessagePack::Unpacker.new.feed_each(body) {|row|
         | 
| 399 | 
            -
                    result << row
         | 
| 400 | 
            -
                  }
         | 
| 401 | 
            -
                  return result
         | 
| 402 | 
            -
                end
         | 
| 403 | 
            -
              end
         | 
| 404 | 
            -
             | 
| 405 | 
            -
             | 
| 406 | 
            -
              ####
         | 
| 407 | 
            -
              ## Job API
         | 
| 408 | 
            -
              ##
         | 
| 409 | 
            -
             | 
| 410 | 
            -
              # => [(jobId:String, type:Symbol, status:String, start_at:String, end_at:String, result_url:String)]
         | 
| 411 | 
            -
              def list_jobs(from=0, to=nil, status=nil, conditions=nil)
         | 
| 412 | 
            -
                params = {}
         | 
| 413 | 
            -
                params['from'] = from.to_s if from
         | 
| 414 | 
            -
                params['to'] = to.to_s if to
         | 
| 415 | 
            -
                params['status'] = status.to_s if status
         | 
| 416 | 
            -
                params.merge!(conditions) if conditions
         | 
| 417 | 
            -
                code, body, res = get("/v3/job/list", params)
         | 
| 418 | 
            -
                if code != "200"
         | 
| 419 | 
            -
                  raise_error("List jobs failed", res)
         | 
| 420 | 
            -
                end
         | 
| 421 | 
            -
                js = checked_json(body, %w[jobs])
         | 
| 422 | 
            -
                result = []
         | 
| 423 | 
            -
                js['jobs'].each {|m|
         | 
| 424 | 
            -
                  job_id = m['job_id']
         | 
| 425 | 
            -
                  type = (m['type'] || '?').to_sym
         | 
| 426 | 
            -
                  database = m['database']
         | 
| 427 | 
            -
                  status = m['status']
         | 
| 428 | 
            -
                  query = m['query']
         | 
| 429 | 
            -
                  start_at = m['start_at']
         | 
| 430 | 
            -
                  end_at = m['end_at']
         | 
| 431 | 
            -
                  cpu_time = m['cpu_time']
         | 
| 432 | 
            -
                  result_size = m['result_size'] # compressed result size in msgpack.gz format
         | 
| 433 | 
            -
                  result_url = m['result']
         | 
| 434 | 
            -
                  priority = m['priority']
         | 
| 435 | 
            -
                  retry_limit = m['retry_limit']
         | 
| 436 | 
            -
                  result << [job_id, type, status, query, start_at, end_at, cpu_time,
         | 
| 437 | 
            -
                             result_size, result_url, priority, retry_limit, nil, database]
         | 
| 438 | 
            -
                }
         | 
| 439 | 
            -
                return result
         | 
| 440 | 
            -
              end
         | 
| 441 | 
            -
             | 
| 442 | 
            -
              # => (type:Symbol, status:String, result:String, url:String, result:String)
         | 
| 443 | 
            -
              def show_job(job_id)
         | 
| 444 | 
            -
                # use v3/job/status instead of v3/job/show to poll finish of a job
         | 
| 445 | 
            -
                code, body, res = get("/v3/job/show/#{e job_id}")
         | 
| 446 | 
            -
                if code != "200"
         | 
| 447 | 
            -
                  raise_error("Show job failed", res)
         | 
| 448 | 
            -
                end
         | 
| 449 | 
            -
                js = checked_json(body, %w[status])
         | 
| 450 | 
            -
                # TODO debug
         | 
| 451 | 
            -
                type = (js['type'] || '?').to_sym  # TODO
         | 
| 452 | 
            -
                database = js['database']
         | 
| 453 | 
            -
                query = js['query']
         | 
| 454 | 
            -
                status = js['status']
         | 
| 455 | 
            -
                debug = js['debug']
         | 
| 456 | 
            -
                url = js['url']
         | 
| 457 | 
            -
                start_at = js['start_at']
         | 
| 458 | 
            -
                end_at = js['end_at']
         | 
| 459 | 
            -
                cpu_time = js['cpu_time']
         | 
| 460 | 
            -
                result_size = js['result_size'] # compressed result size in msgpack.gz format
         | 
| 461 | 
            -
                result = js['result'] # result target URL
         | 
| 462 | 
            -
                hive_result_schema = (js['hive_result_schema'] || '')
         | 
| 463 | 
            -
                if hive_result_schema.empty?
         | 
| 464 | 
            -
                  hive_result_schema = nil
         | 
| 465 | 
            -
                else
         | 
| 466 | 
            -
                  begin
         | 
| 467 | 
            -
                    hive_result_schema = JSON.parse(hive_result_schema)
         | 
| 468 | 
            -
                  rescue JSON::ParserError => e
         | 
| 469 | 
            -
                    # this is a workaround for a Known Limitation in the Pig Engine which does not set a default, auto-generated
         | 
| 470 | 
            -
                    #   column name for anonymous columns (such as the ones that are generated from UDF like COUNT or SUM).
         | 
| 471 | 
            -
                    # The schema will contain 'nil' for the name of those columns and that breaks the JSON parser since it violates
         | 
| 472 | 
            -
                    #   the JSON syntax standard.
         | 
| 473 | 
            -
                    if type == :pig and hive_result_schema !~ /[\{\}]/
         | 
| 474 | 
            -
                      begin
         | 
| 475 | 
            -
                        # NOTE: this works because a JSON 2 dimensional array is the same as a Ruby one.
         | 
| 476 | 
            -
                        #   Any change in the format for the hive_result_schema output may cause a syntax error, in which case
         | 
| 477 | 
            -
                        #   this lame attempt at fixing the problem will fail and we will be raising the original JSON exception
         | 
| 478 | 
            -
                        hive_result_schema = eval(hive_result_schema)
         | 
| 479 | 
            -
                      rescue SyntaxError => ignored_e
         | 
| 480 | 
            -
                        raise e
         | 
| 481 | 
            -
                      end
         | 
| 482 | 
            -
                      hive_result_schema.each_with_index {|col_schema, idx|
         | 
| 483 | 
            -
                        if col_schema[0].nil?
         | 
| 484 | 
            -
                          col_schema[0] = "_col#{idx}"
         | 
| 485 | 
            -
                        end
         | 
| 486 | 
            -
                      }
         | 
| 487 | 
            -
                    else
         | 
| 488 | 
            -
                      raise e
         | 
| 489 | 
            -
                    end
         | 
| 490 | 
            -
                  end
         | 
| 491 | 
            -
                end
         | 
| 492 | 
            -
                priority = js['priority']
         | 
| 493 | 
            -
                retry_limit = js['retry_limit']
         | 
| 494 | 
            -
                return [type, query, status, url, debug, start_at, end_at, cpu_time,
         | 
| 495 | 
            -
                        result_size, result, hive_result_schema, priority, retry_limit, nil, database]
         | 
| 496 | 
            -
              end
         | 
| 497 | 
            -
             | 
| 498 | 
            -
              def job_status(job_id)
         | 
| 499 | 
            -
                code, body, res = get("/v3/job/status/#{e job_id}")
         | 
| 500 | 
            -
                if code != "200"
         | 
| 501 | 
            -
                  raise_error("Get job status failed", res)
         | 
| 502 | 
            -
                end
         | 
| 503 | 
            -
             | 
| 504 | 
            -
                js = checked_json(body, %w[status])
         | 
| 505 | 
            -
                return js['status']
         | 
| 506 | 
            -
              end
         | 
| 507 | 
            -
             | 
| 508 | 
            -
              def job_result(job_id)
         | 
| 509 | 
            -
                require 'msgpack'
         | 
| 510 | 
            -
                code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>'msgpack'})
         | 
| 511 | 
            -
                if code != "200"
         | 
| 512 | 
            -
                  raise_error("Get job result failed", res)
         | 
| 513 | 
            -
                end
         | 
| 514 | 
            -
                result = []
         | 
| 515 | 
            -
                MessagePack::Unpacker.new.feed_each(body) {|row|
         | 
| 516 | 
            -
                  result << row
         | 
| 517 | 
            -
                }
         | 
| 518 | 
            -
                return result
         | 
| 519 | 
            -
              end
         | 
| 520 | 
            -
             | 
| 521 | 
            -
              # block is optional and must accept 1 parameter
         | 
| 522 | 
            -
              def job_result_format(job_id, format, io=nil, &block)
         | 
| 523 | 
            -
                if io
         | 
| 524 | 
            -
                  code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>format}) {|res|
         | 
| 525 | 
            -
                    if res.code != "200"
         | 
| 526 | 
            -
                      raise_error("Get job result failed", res)
         | 
| 527 | 
            -
                    end
         | 
| 528 | 
            -
             | 
| 529 | 
            -
                    if ce = res.header['Content-Encoding']
         | 
| 530 | 
            -
                      require 'zlib'
         | 
| 531 | 
            -
                      res.extend(DeflateReadBodyMixin)
         | 
| 532 | 
            -
                      res.gzip = true if ce == 'gzip'
         | 
| 533 | 
            -
                    else
         | 
| 534 | 
            -
                      res.extend(DirectReadBodyMixin)
         | 
| 535 | 
            -
                    end
         | 
| 536 | 
            -
             | 
| 537 | 
            -
                    res.extend(DirectReadBodyMixin)
         | 
| 538 | 
            -
                    if ce = res.header['Content-Encoding']
         | 
| 539 | 
            -
                      if ce == 'gzip'
         | 
| 540 | 
            -
                        infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
         | 
| 541 | 
            -
                      else
         | 
| 542 | 
            -
                        infl = Zlib::Inflate.new
         | 
| 543 | 
            -
                      end
         | 
| 544 | 
            -
                    end
         | 
| 545 | 
            -
             | 
| 546 | 
            -
                    total_compr_size = 0
         | 
| 547 | 
            -
                    res.each_fragment {|fragment|
         | 
| 548 | 
            -
                      total_compr_size += fragment.size
         | 
| 549 | 
            -
                      # uncompressed if the 'Content-Enconding' header is set in response
         | 
| 550 | 
            -
                      fragment = infl.inflate(fragment) if ce
         | 
| 551 | 
            -
                      io.write(fragment)
         | 
| 552 | 
            -
                      block.call(total_compr_size) if block_given?
         | 
| 553 | 
            -
                    }
         | 
| 554 | 
            -
                  }
         | 
| 555 | 
            -
                  nil
         | 
| 556 | 
            -
                else
         | 
| 557 | 
            -
                  code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>format})
         | 
| 558 | 
            -
                  if res.code != "200"
         | 
| 559 | 
            -
                    raise_error("Get job result failed", res)
         | 
| 560 | 
            -
                  end
         | 
| 561 | 
            -
                  body
         | 
| 562 | 
            -
                end
         | 
| 563 | 
            -
              end
         | 
| 564 | 
            -
             | 
| 565 | 
            -
              # block is optional and must accept 1 argument
         | 
| 566 | 
            -
              def job_result_each(job_id, &block)
         | 
| 567 | 
            -
                require 'msgpack'
         | 
| 568 | 
            -
                get("/v3/job/result/#{e job_id}", {'format'=>'msgpack'}) {|res|
         | 
| 569 | 
            -
                  if res.code != "200"
         | 
| 570 | 
            -
                    raise_error("Get job result failed", res)
         | 
| 571 | 
            -
                  end
         | 
| 572 | 
            -
             | 
| 573 | 
            -
                  # default to decompressing the response since format is fixed to 'msgpack'
         | 
| 574 | 
            -
                  res.extend(DeflateReadBodyMixin)
         | 
| 575 | 
            -
                  res.gzip = (res.header['Content-Encoding'] == 'gzip')
         | 
| 576 | 
            -
                  upkr = MessagePack::Unpacker.new
         | 
| 577 | 
            -
                  res.each_fragment {|inflated_fragment|
         | 
| 578 | 
            -
                    upkr.feed_each(inflated_fragment, &block)
         | 
| 579 | 
            -
                  }
         | 
| 580 | 
            -
                }
         | 
| 581 | 
            -
                nil
         | 
| 582 | 
            -
              end
         | 
| 583 | 
            -
             | 
| 584 | 
            -
              # block is optional and must accept 1 argument
         | 
| 585 | 
            -
              def job_result_each_with_compr_size(job_id, &block)
         | 
| 586 | 
            -
                require 'zlib'
         | 
| 587 | 
            -
                require 'msgpack'
         | 
| 588 | 
            -
             | 
| 589 | 
            -
                get("/v3/job/result/#{e job_id}", {'format'=>'msgpack'}) {|res|
         | 
| 590 | 
            -
                  if res.code != "200"
         | 
| 591 | 
            -
                    raise_error("Get job result failed", res)
         | 
| 592 | 
            -
                  end
         | 
| 593 | 
            -
             | 
| 594 | 
            -
                  res.extend(DirectReadBodyMixin)
         | 
| 595 | 
            -
                  if res.header['Content-Encoding'] == 'gzip'
         | 
| 596 | 
            -
                    infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
         | 
| 597 | 
            -
                  else
         | 
| 598 | 
            -
                    infl = Zlib::Inflate.new
         | 
| 599 | 
            -
                  end
         | 
| 600 | 
            -
                  upkr = MessagePack::Unpacker.new
         | 
| 601 | 
            -
                  begin
         | 
| 602 | 
            -
                    total_compr_size = 0
         | 
| 603 | 
            -
                    res.each_fragment {|fragment|
         | 
| 604 | 
            -
                      total_compr_size += fragment.size
         | 
| 605 | 
            -
                      upkr.feed_each(infl.inflate(fragment)) {|unpacked|
         | 
| 606 | 
            -
                        block.call(unpacked, total_compr_size) if block_given?
         | 
| 607 | 
            -
                      }
         | 
| 608 | 
            -
                    }
         | 
| 609 | 
            -
                  ensure
         | 
| 610 | 
            -
                    infl.close
         | 
| 611 | 
            -
                  end
         | 
| 612 | 
            -
                }
         | 
| 613 | 
            -
                nil
         | 
| 614 | 
            -
              end
         | 
| 615 | 
            -
             | 
| 616 | 
            -
              def job_result_raw(job_id, format)
         | 
| 617 | 
            -
                code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>format})
         | 
| 618 | 
            -
                if code != "200"
         | 
| 619 | 
            -
                  raise_error("Get job result failed", res)
         | 
| 620 | 
            -
                end
         | 
| 621 | 
            -
                return body
         | 
| 622 | 
            -
              end
         | 
| 623 | 
            -
             | 
| 624 | 
            -
              def kill(job_id)
         | 
| 625 | 
            -
                code, body, res = post("/v3/job/kill/#{e job_id}")
         | 
| 626 | 
            -
                if code != "200"
         | 
| 627 | 
            -
                  raise_error("Kill job failed", res)
         | 
| 628 | 
            -
                end
         | 
| 629 | 
            -
                js = checked_json(body, %w[])
         | 
| 630 | 
            -
                former_status = js['former_status']
         | 
| 631 | 
            -
                return former_status
         | 
| 632 | 
            -
              end
         | 
| 633 | 
            -
             | 
| 634 | 
            -
              # => jobId:String
         | 
| 635 | 
            -
              def hive_query(q, db=nil, result_url=nil, priority=nil, retry_limit=nil, opts={})
         | 
| 636 | 
            -
                query(q, :hive, db, result_url, priority, retry_limit, opts)
         | 
| 637 | 
            -
              end
         | 
| 638 | 
            -
             | 
| 639 | 
            -
              # => jobId:String
         | 
| 640 | 
            -
              def pig_query(q, db=nil, result_url=nil, priority=nil, retry_limit=nil, opts={})
         | 
| 641 | 
            -
                query(q, :pig, db, result_url, priority, retry_limit, opts)
         | 
| 642 | 
            -
              end
         | 
| 643 | 
            -
             | 
| 644 | 
            -
              # => jobId:String
         | 
| 645 | 
            -
              def query(q, type=:hive, db=nil, result_url=nil, priority=nil, retry_limit=nil, opts={})
         | 
| 646 | 
            -
                params = {'query' => q}.merge(opts)
         | 
| 647 | 
            -
                params['result'] = result_url if result_url
         | 
| 648 | 
            -
                params['priority'] = priority if priority
         | 
| 649 | 
            -
                params['retry_limit'] = retry_limit if retry_limit
         | 
| 650 | 
            -
                code, body, res = post("/v3/job/issue/#{type}/#{e db}", params)
         | 
| 651 | 
            -
                if code != "200"
         | 
| 652 | 
            -
                  raise_error("Query failed", res)
         | 
| 653 | 
            -
                end
         | 
| 654 | 
            -
                js = checked_json(body, %w[job_id])
         | 
| 655 | 
            -
                return js['job_id'].to_s
         | 
| 656 | 
            -
              end
         | 
| 657 | 
            -
             | 
| 658 | 
            -
              ####
         | 
| 659 | 
            -
              ## Export API
         | 
| 660 | 
            -
              ##
         | 
| 661 | 
            -
             | 
| 662 | 
            -
              # => jobId:String
         | 
| 663 | 
            -
              def export(db, table, storage_type, opts={})
         | 
| 664 | 
            -
                params = opts.dup
         | 
| 665 | 
            -
                params['storage_type'] = storage_type
         | 
| 666 | 
            -
                code, body, res = post("/v3/export/run/#{e db}/#{e table}", params)
         | 
| 667 | 
            -
                if code != "200"
         | 
| 668 | 
            -
                  raise_error("Export failed", res)
         | 
| 669 | 
            -
                end
         | 
| 670 | 
            -
                js = checked_json(body, %w[job_id])
         | 
| 671 | 
            -
                return js['job_id'].to_s
         | 
| 672 | 
            -
              end
         | 
| 673 | 
            -
             | 
| 674 | 
            -
             | 
| 675 | 
            -
              ####
         | 
| 676 | 
            -
              ## Partial delete API
         | 
| 677 | 
            -
              ##
         | 
| 678 | 
            -
             | 
| 679 | 
            -
              def partial_delete(db, table, to, from, opts={})
         | 
| 680 | 
            -
                params = opts.dup
         | 
| 681 | 
            -
                params['to'] = to.to_s
         | 
| 682 | 
            -
                params['from'] = from.to_s
         | 
| 683 | 
            -
                code, body, res = post("/v3/table/partialdelete/#{e db}/#{e table}", params)
         | 
| 684 | 
            -
                if code != "200"
         | 
| 685 | 
            -
                  raise_error("Partial delete failed", res)
         | 
| 686 | 
            -
                end
         | 
| 687 | 
            -
                js = checked_json(body, %w[job_id])
         | 
| 688 | 
            -
                return js['job_id'].to_s
         | 
| 689 | 
            -
              end
         | 
| 690 | 
            -
             | 
| 691 | 
            -
              ####
         | 
| 692 | 
            -
              ## Bulk import API
         | 
| 693 | 
            -
              ##
         | 
| 694 | 
            -
             | 
| 695 | 
            -
              # => nil
         | 
| 696 | 
            -
              def create_bulk_import(name, db, table, opts={})
         | 
| 697 | 
            -
                params = opts.dup
         | 
| 698 | 
            -
                code, body, res = post("/v3/bulk_import/create/#{e name}/#{e db}/#{e table}", params)
         | 
| 699 | 
            -
                if code != "200"
         | 
| 700 | 
            -
                  raise_error("Create bulk import failed", res)
         | 
| 701 | 
            -
                end
         | 
| 702 | 
            -
                return nil
         | 
| 703 | 
            -
              end
         | 
| 704 | 
            -
             | 
| 705 | 
            -
              # => nil
         | 
| 706 | 
            -
              def delete_bulk_import(name, opts={})
         | 
| 707 | 
            -
                params = opts.dup
         | 
| 708 | 
            -
                code, body, res = post("/v3/bulk_import/delete/#{e name}", params)
         | 
| 709 | 
            -
                if code != "200"
         | 
| 710 | 
            -
                  raise_error("Delete bulk import failed", res)
         | 
| 711 | 
            -
                end
         | 
| 712 | 
            -
                return nil
         | 
| 713 | 
            -
              end
         | 
| 714 | 
            -
             | 
| 715 | 
            -
              # => data:Hash
         | 
| 716 | 
            -
              def show_bulk_import(name)
         | 
| 717 | 
            -
                code, body, res = get("/v3/bulk_import/show/#{name}")
         | 
| 718 | 
            -
                if code != "200"
         | 
| 719 | 
            -
                  raise_error("Show bulk import failed", res)
         | 
| 720 | 
            -
                end
         | 
| 721 | 
            -
                js = checked_json(body, %w[status])
         | 
| 722 | 
            -
                return js
         | 
| 723 | 
            -
              end
         | 
| 724 | 
            -
             | 
| 725 | 
            -
              # => result:[data:Hash]
         | 
| 726 | 
            -
              def list_bulk_imports(opts={})
         | 
| 727 | 
            -
                params = opts.dup
         | 
| 728 | 
            -
                code, body, res = get("/v3/bulk_import/list", params)
         | 
| 729 | 
            -
                if code != "200"
         | 
| 730 | 
            -
                  raise_error("List bulk imports failed", res)
         | 
| 731 | 
            -
                end
         | 
| 732 | 
            -
                js = checked_json(body, %w[bulk_imports])
         | 
| 733 | 
            -
                return js['bulk_imports']
         | 
| 734 | 
            -
              end
         | 
| 735 | 
            -
             | 
| 736 | 
            -
              def list_bulk_import_parts(name, opts={})
         | 
| 737 | 
            -
                params = opts.dup
         | 
| 738 | 
            -
                code, body, res = get("/v3/bulk_import/list_parts/#{e name}", params)
         | 
| 739 | 
            -
                if code != "200"
         | 
| 740 | 
            -
                  raise_error("List bulk import parts failed", res)
         | 
| 741 | 
            -
                end
         | 
| 742 | 
            -
                js = checked_json(body, %w[parts])
         | 
| 743 | 
            -
                return js['parts']
         | 
| 744 | 
            -
              end
         | 
| 745 | 
            -
             | 
| 746 | 
            -
              # => nil
         | 
| 747 | 
            -
              def bulk_import_upload_part(name, part_name, stream, size, opts={})
         | 
| 748 | 
            -
                code, body, res = put("/v3/bulk_import/upload_part/#{e name}/#{e part_name}", stream, size)
         | 
| 749 | 
            -
                if code[0] != ?2
         | 
| 750 | 
            -
                  raise_error("Upload a part failed", res)
         | 
| 751 | 
            -
                end
         | 
| 752 | 
            -
                return nil
         | 
| 753 | 
            -
              end
         | 
| 754 | 
            -
             | 
| 755 | 
            -
              # => nil
         | 
| 756 | 
            -
              def bulk_import_delete_part(name, part_name, opts={})
         | 
| 757 | 
            -
                params = opts.dup
         | 
| 758 | 
            -
                code, body, res = post("/v3/bulk_import/delete_part/#{e name}/#{e part_name}", params)
         | 
| 759 | 
            -
                if code[0] != ?2
         | 
| 760 | 
            -
                  raise_error("Delete a part failed", res)
         | 
| 761 | 
            -
                end
         | 
| 762 | 
            -
                return nil
         | 
| 763 | 
            -
              end
         | 
| 764 | 
            -
             | 
| 765 | 
            -
              # => nil
         | 
| 766 | 
            -
              def freeze_bulk_import(name, opts={})
         | 
| 767 | 
            -
                params = opts.dup
         | 
| 768 | 
            -
                code, body, res = post("/v3/bulk_import/freeze/#{e name}", params)
         | 
| 769 | 
            -
                if code != "200"
         | 
| 770 | 
            -
                  raise_error("Freeze bulk import failed", res)
         | 
| 771 | 
            -
                end
         | 
| 772 | 
            -
                return nil
         | 
| 773 | 
            -
              end
         | 
| 774 | 
            -
             | 
| 775 | 
            -
              # => nil
         | 
| 776 | 
            -
              def unfreeze_bulk_import(name, opts={})
         | 
| 777 | 
            -
                params = opts.dup
         | 
| 778 | 
            -
                code, body, res = post("/v3/bulk_import/unfreeze/#{e name}", params)
         | 
| 779 | 
            -
                if code != "200"
         | 
| 780 | 
            -
                  raise_error("Unfreeze bulk import failed", res)
         | 
| 781 | 
            -
                end
         | 
| 782 | 
            -
                return nil
         | 
| 783 | 
            -
              end
         | 
| 784 | 
            -
             | 
| 785 | 
            -
              # => jobId:String
         | 
| 786 | 
            -
              def perform_bulk_import(name, opts={})
         | 
| 787 | 
            -
                params = opts.dup
         | 
| 788 | 
            -
                code, body, res = post("/v3/bulk_import/perform/#{e name}", params)
         | 
| 789 | 
            -
                if code != "200"
         | 
| 790 | 
            -
                  raise_error("Perform bulk import failed", res)
         | 
| 791 | 
            -
                end
         | 
| 792 | 
            -
                js = checked_json(body, %w[job_id])
         | 
| 793 | 
            -
                return js['job_id'].to_s
         | 
| 794 | 
            -
              end
         | 
| 795 | 
            -
             | 
| 796 | 
            -
              # => nil
         | 
| 797 | 
            -
              def commit_bulk_import(name, opts={})
         | 
| 798 | 
            -
                params = opts.dup
         | 
| 799 | 
            -
                code, body, res = post("/v3/bulk_import/commit/#{e name}", params)
         | 
| 800 | 
            -
                if code != "200"
         | 
| 801 | 
            -
                  raise_error("Commit bulk import failed", res)
         | 
| 802 | 
            -
                end
         | 
| 803 | 
            -
                return nil
         | 
| 804 | 
            -
              end
         | 
| 805 | 
            -
             | 
| 806 | 
            -
              # => data...
         | 
| 807 | 
            -
              def bulk_import_error_records(name, opts={}, &block)
         | 
| 808 | 
            -
                params = opts.dup
         | 
| 809 | 
            -
                code, body, res = get("/v3/bulk_import/error_records/#{e name}", params)
         | 
| 810 | 
            -
                if code != "200"
         | 
| 811 | 
            -
                  raise_error("Failed to get bulk import error records", res)
         | 
| 812 | 
            -
                end
         | 
| 813 | 
            -
                if body.empty?
         | 
| 814 | 
            -
                  if block
         | 
| 815 | 
            -
                    return nil
         | 
| 816 | 
            -
                  else
         | 
| 817 | 
            -
                    return []
         | 
| 818 | 
            -
                  end
         | 
| 819 | 
            -
                end
         | 
| 820 | 
            -
                require 'zlib'
         | 
| 821 | 
            -
                require 'stringio'
         | 
| 822 | 
            -
                require 'msgpack'
         | 
| 823 | 
            -
                require File.expand_path('compat_gzip_reader', File.dirname(__FILE__))
         | 
| 824 | 
            -
                u = MessagePack::Unpacker.new(Zlib::GzipReader.new(StringIO.new(body)))
         | 
| 825 | 
            -
                if block
         | 
| 826 | 
            -
                  begin
         | 
| 827 | 
            -
                    u.each(&block)
         | 
| 828 | 
            -
                  rescue EOFError
         | 
| 829 | 
            -
                  end
         | 
| 830 | 
            -
                  nil
         | 
| 831 | 
            -
                else
         | 
| 832 | 
            -
                  result = []
         | 
| 833 | 
            -
                  begin
         | 
| 834 | 
            -
                    u.each {|row|
         | 
| 835 | 
            -
                      result << row
         | 
| 836 | 
            -
                    }
         | 
| 837 | 
            -
                  rescue EOFError
         | 
| 838 | 
            -
                  end
         | 
| 839 | 
            -
                  return result
         | 
| 840 | 
            -
                end
         | 
| 841 | 
            -
              end
         | 
| 842 | 
            -
             | 
| 843 | 
            -
              ####
         | 
| 844 | 
            -
              ## Schedule API
         | 
| 845 | 
            -
              ##
         | 
| 846 | 
            -
             | 
| 847 | 
            -
              # => start:String
         | 
| 848 | 
            -
              def create_schedule(name, opts)
         | 
| 849 | 
            -
                params = opts.update({:type=> opts[:type] || opts['type'] || 'hive'})
         | 
| 850 | 
            -
                code, body, res = post("/v3/schedule/create/#{e name}", params)
         | 
| 851 | 
            -
                if code != "200"
         | 
| 852 | 
            -
                  raise_error("Create schedule failed", res)
         | 
| 853 | 
            -
                end
         | 
| 854 | 
            -
                js = checked_json(body, %w[start])
         | 
| 855 | 
            -
                return js['start']
         | 
| 856 | 
            -
              end
         | 
| 857 | 
            -
             | 
| 858 | 
            -
              # => cron:String, query:String
         | 
| 859 | 
            -
              def delete_schedule(name)
         | 
| 860 | 
            -
                code, body, res = post("/v3/schedule/delete/#{e name}")
         | 
| 861 | 
            -
                if code != "200"
         | 
| 862 | 
            -
                  raise_error("Delete schedule failed", res)
         | 
| 863 | 
            -
                end
         | 
| 864 | 
            -
                js = checked_json(body, %w[])
         | 
| 865 | 
            -
                return js['cron'], js["query"]
         | 
| 866 | 
            -
              end
         | 
| 867 | 
            -
             | 
| 868 | 
            -
              # => [(name:String, cron:String, query:String, database:String, result_url:String)]
         | 
| 869 | 
            -
              def list_schedules
         | 
| 870 | 
            -
                code, body, res = get("/v3/schedule/list")
         | 
| 871 | 
            -
                if code != "200"
         | 
| 872 | 
            -
                  raise_error("List schedules failed", res)
         | 
| 873 | 
            -
                end
         | 
| 874 | 
            -
                js = checked_json(body, %w[schedules])
         | 
| 875 | 
            -
                result = []
         | 
| 876 | 
            -
                js['schedules'].each {|m|
         | 
| 877 | 
            -
                  name = m['name']
         | 
| 878 | 
            -
                  cron = m['cron']
         | 
| 879 | 
            -
                  query = m['query']
         | 
| 880 | 
            -
                  database = m['database']
         | 
| 881 | 
            -
                  result_url = m['result']
         | 
| 882 | 
            -
                  timezone = m['timezone']
         | 
| 883 | 
            -
                  delay = m['delay']
         | 
| 884 | 
            -
                  next_time = m['next_time']
         | 
| 885 | 
            -
                  priority = m['priority']
         | 
| 886 | 
            -
                  retry_limit = m['retry_limit']
         | 
| 887 | 
            -
                  result << [name, cron, query, database, result_url, timezone, delay, next_time, priority, retry_limit, nil] # same as database
         | 
| 888 | 
            -
                }
         | 
| 889 | 
            -
                return result
         | 
| 890 | 
            -
              end
         | 
| 891 | 
            -
             | 
| 892 | 
            -
              def update_schedule(name, params)
         | 
| 893 | 
            -
                code, body, res = post("/v3/schedule/update/#{e name}", params)
         | 
| 894 | 
            -
                if code != "200"
         | 
| 895 | 
            -
                  raise_error("Update schedule failed", res)
         | 
| 896 | 
            -
                end
         | 
| 897 | 
            -
                return nil
         | 
| 898 | 
            -
              end
         | 
| 899 | 
            -
             | 
| 900 | 
            -
              def history(name, from=0, to=nil)
         | 
| 901 | 
            -
                params = {}
         | 
| 902 | 
            -
                params['from'] = from.to_s if from
         | 
| 903 | 
            -
                params['to'] = to.to_s if to
         | 
| 904 | 
            -
                code, body, res = get("/v3/schedule/history/#{e name}", params)
         | 
| 905 | 
            -
                if code != "200"
         | 
| 906 | 
            -
                  raise_error("List history failed", res)
         | 
| 907 | 
            -
                end
         | 
| 908 | 
            -
                js = checked_json(body, %w[history])
         | 
| 909 | 
            -
                result = []
         | 
| 910 | 
            -
                js['history'].each {|m|
         | 
| 911 | 
            -
                  job_id = m['job_id']
         | 
| 912 | 
            -
                  type = (m['type'] || '?').to_sym
         | 
| 913 | 
            -
                  database = m['database']
         | 
| 914 | 
            -
                  status = m['status']
         | 
| 915 | 
            -
                  query = m['query']
         | 
| 916 | 
            -
                  start_at = m['start_at']
         | 
| 917 | 
            -
                  end_at = m['end_at']
         | 
| 918 | 
            -
                  scheduled_at = m['scheduled_at']
         | 
| 919 | 
            -
                  result_url = m['result']
         | 
| 920 | 
            -
                  priority = m['priority']
         | 
| 921 | 
            -
                  result << [scheduled_at, job_id, type, status, query, start_at, end_at, result_url, priority, database]
         | 
| 922 | 
            -
                }
         | 
| 923 | 
            -
                return result
         | 
| 924 | 
            -
              end
         | 
| 925 | 
            -
             | 
| 926 | 
            -
              def run_schedule(name, time, num)
         | 
| 927 | 
            -
                params = {}
         | 
| 928 | 
            -
                params = {'num' => num} if num
         | 
| 929 | 
            -
                code, body, res = post("/v3/schedule/run/#{e name}/#{e time}", params)
         | 
| 930 | 
            -
                if code != "200"
         | 
| 931 | 
            -
                  raise_error("Run schedule failed", res)
         | 
| 932 | 
            -
                end
         | 
| 933 | 
            -
                js = checked_json(body, %w[jobs])
         | 
| 934 | 
            -
                result = []
         | 
| 935 | 
            -
                js['jobs'].each {|m|
         | 
| 936 | 
            -
                  job_id = m['job_id']
         | 
| 937 | 
            -
                  scheduled_at = m['scheduled_at']
         | 
| 938 | 
            -
                  type = (m['type'] || '?').to_sym
         | 
| 939 | 
            -
                  result << [job_id, type, scheduled_at]
         | 
| 940 | 
            -
                }
         | 
| 941 | 
            -
                return result
         | 
| 942 | 
            -
              end
         | 
| 943 | 
            -
             | 
| 944 | 
            -
              ####
         | 
| 945 | 
            -
              ## Import API
         | 
| 946 | 
            -
              ##
         | 
| 947 | 
            -
             | 
| 948 | 
            -
              # => time:Float
         | 
| 949 | 
            -
              def import(db, table, format, stream, size, unique_id=nil)
         | 
| 950 | 
            -
                if unique_id
         | 
| 951 | 
            -
                  path = "/v3/table/import_with_id/#{e db}/#{e table}/#{unique_id}/#{format}"
         | 
| 952 | 
            -
                else
         | 
| 953 | 
            -
                  path = "/v3/table/import/#{e db}/#{e table}/#{format}"
         | 
| 954 | 
            -
                end
         | 
| 955 | 
            -
                opts = {}
         | 
| 956 | 
            -
                if @host == DEFAULT_ENDPOINT
         | 
| 957 | 
            -
                  opts[:host] = DEFAULT_IMPORT_ENDPOINT
         | 
| 958 | 
            -
                elsif @host == NEW_DEFAULT_ENDPOINT
         | 
| 959 | 
            -
                  opts[:host] = NEW_DEFAULT_IMPORT_ENDPOINT
         | 
| 960 | 
            -
                end
         | 
| 961 | 
            -
                code, body, res = put(path, stream, size, opts)
         | 
| 962 | 
            -
                if code[0] != ?2
         | 
| 963 | 
            -
                  raise_error("Import failed", res)
         | 
| 964 | 
            -
                end
         | 
| 965 | 
            -
                js = checked_json(body, %w[])
         | 
| 966 | 
            -
                time = js['elapsed_time'].to_f
         | 
| 967 | 
            -
                return time
         | 
| 968 | 
            -
              end
         | 
| 969 | 
            -
             | 
| 970 | 
            -
             | 
| 971 | 
            -
              ####
         | 
| 972 | 
            -
              ## Result API
         | 
| 973 | 
            -
              ##
         | 
| 974 | 
            -
             | 
| 975 | 
            -
              def list_result
         | 
| 976 | 
            -
                code, body, res = get("/v3/result/list")
         | 
| 977 | 
            -
                if code != "200"
         | 
| 978 | 
            -
                  raise_error("List result table failed", res)
         | 
| 979 | 
            -
                end
         | 
| 980 | 
            -
                js = checked_json(body, %w[results])
         | 
| 981 | 
            -
                result = []
         | 
| 982 | 
            -
                js['results'].map {|m|
         | 
| 983 | 
            -
                  result << [m['name'], m['url'], nil] # same as database
         | 
| 984 | 
            -
                }
         | 
| 985 | 
            -
                return result
         | 
| 986 | 
            -
              end
         | 
| 987 | 
            -
             | 
| 988 | 
            -
              # => true
         | 
| 989 | 
            -
              def create_result(name, url, opts={})
         | 
| 990 | 
            -
                params = {'url'=>url}.merge(opts)
         | 
| 991 | 
            -
                code, body, res = post("/v3/result/create/#{e name}", params)
         | 
| 992 | 
            -
                if code != "200"
         | 
| 993 | 
            -
                  raise_error("Create result table failed", res)
         | 
| 994 | 
            -
                end
         | 
| 995 | 
            -
                return true
         | 
| 996 | 
            -
              end
         | 
| 997 | 
            -
             | 
| 998 | 
            -
              # => true
         | 
| 999 | 
            -
              def delete_result(name)
         | 
| 1000 | 
            -
                code, body, res = post("/v3/result/delete/#{e name}")
         | 
| 1001 | 
            -
                if code != "200"
         | 
| 1002 | 
            -
                  raise_error("Delete result table failed", res)
         | 
| 1003 | 
            -
                end
         | 
| 1004 | 
            -
                return true
         | 
| 1005 | 
            -
              end
         | 
| 1006 | 
            -
             | 
| 1007 | 
            -
             | 
| 1008 | 
            -
              ####
         | 
| 1009 | 
            -
              ## User API
         | 
| 1010 | 
            -
              ##
         | 
| 1011 | 
            -
             | 
| 1012 | 
            -
              # apikey:String
         | 
| 1013 | 
            -
              def authenticate(user, password)
         | 
| 1014 | 
            -
                code, body, res = post("/v3/user/authenticate", {'user'=>user, 'password'=>password})
         | 
| 1015 | 
            -
                if code != "200"
         | 
| 1016 | 
            -
                  if code == "400"
         | 
| 1017 | 
            -
                    raise_error("Authentication failed", res, AuthError)
         | 
| 1018 | 
            -
                  else
         | 
| 1019 | 
            -
                    raise_error("Authentication failed", res)
         | 
| 1020 | 
            -
                  end
         | 
| 1021 | 
            -
                end
         | 
| 1022 | 
            -
                js = checked_json(body, %w[apikey])
         | 
| 1023 | 
            -
                apikey = js['apikey']
         | 
| 1024 | 
            -
                return apikey
         | 
| 1025 | 
            -
              end
         | 
| 1026 | 
            -
             | 
| 1027 | 
            -
              # => [[name:String,organization:String,[user:String]]
         | 
| 1028 | 
            -
              def list_users
         | 
| 1029 | 
            -
                code, body, res = get("/v3/user/list")
         | 
| 1030 | 
            -
                if code != "200"
         | 
| 1031 | 
            -
                  raise_error("List users failed", res)
         | 
| 1032 | 
            -
                end
         | 
| 1033 | 
            -
                js = checked_json(body, %w[users])
         | 
| 1034 | 
            -
                result = js["users"].map {|roleinfo|
         | 
| 1035 | 
            -
                  name = roleinfo['name']
         | 
| 1036 | 
            -
                  email = roleinfo['email']
         | 
| 1037 | 
            -
                  [name, nil, nil, email] # set nil to org and role for API compatibility
         | 
| 1038 | 
            -
                }
         | 
| 1039 | 
            -
                return result
         | 
| 1040 | 
            -
              end
         | 
| 1041 | 
            -
             | 
| 1042 | 
            -
              # => true
         | 
| 1043 | 
            -
              def add_user(name, org, email, password)
         | 
| 1044 | 
            -
                params = {'organization'=>org, :email=>email, :password=>password}
         | 
| 1045 | 
            -
                code, body, res = post("/v3/user/add/#{e name}", params)
         | 
| 1046 | 
            -
                if code != "200"
         | 
| 1047 | 
            -
                  raise_error("Adding user failed", res)
         | 
| 1048 | 
            -
                end
         | 
| 1049 | 
            -
                return true
         | 
| 1050 | 
            -
              end
         | 
| 1051 | 
            -
             | 
| 1052 | 
            -
              # => true
         | 
| 1053 | 
            -
              def remove_user(user)
         | 
| 1054 | 
            -
                code, body, res = post("/v3/user/remove/#{e user}")
         | 
| 1055 | 
            -
                if code != "200"
         | 
| 1056 | 
            -
                  raise_error("Removing user failed", res)
         | 
| 1057 | 
            -
                end
         | 
| 1058 | 
            -
                return true
         | 
| 1059 | 
            -
              end
         | 
| 1060 | 
            -
             | 
| 1061 | 
            -
              # => true
         | 
| 1062 | 
            -
              def change_email(user, email)
         | 
| 1063 | 
            -
                params = {'email' => email}
         | 
| 1064 | 
            -
                code, body, res = post("/v3/user/email/change/#{e user}", params)
         | 
| 1065 | 
            -
                if code != "200"
         | 
| 1066 | 
            -
                  raise_error("Changing email failed", res)
         | 
| 1067 | 
            -
                end
         | 
| 1068 | 
            -
                return true
         | 
| 1069 | 
            -
              end
         | 
| 1070 | 
            -
             | 
| 1071 | 
            -
              # => [apikey:String]
         | 
| 1072 | 
            -
              def list_apikeys(user)
         | 
| 1073 | 
            -
                code, body, res = get("/v3/user/apikey/list/#{e user}")
         | 
| 1074 | 
            -
                if code != "200"
         | 
| 1075 | 
            -
                  raise_error("List API keys failed", res)
         | 
| 1076 | 
            -
                end
         | 
| 1077 | 
            -
                js = checked_json(body, %w[apikeys])
         | 
| 1078 | 
            -
                return js['apikeys']
         | 
| 1079 | 
            -
              end
         | 
| 1080 | 
            -
             | 
| 1081 | 
            -
              # => true
         | 
| 1082 | 
            -
              def add_apikey(user)
         | 
| 1083 | 
            -
                code, body, res = post("/v3/user/apikey/add/#{e user}")
         | 
| 1084 | 
            -
                if code != "200"
         | 
| 1085 | 
            -
                  raise_error("Adding API key failed", res)
         | 
| 1086 | 
            -
                end
         | 
| 1087 | 
            -
                return true
         | 
| 1088 | 
            -
              end
         | 
| 1089 | 
            -
             | 
| 1090 | 
            -
              # => true
         | 
| 1091 | 
            -
              def remove_apikey(user, apikey)
         | 
| 1092 | 
            -
                params = {'apikey' => apikey}
         | 
| 1093 | 
            -
                code, body, res = post("/v3/user/apikey/remove/#{e user}", params)
         | 
| 1094 | 
            -
                if code != "200"
         | 
| 1095 | 
            -
                  raise_error("Removing API key failed", res)
         | 
| 1096 | 
            -
                end
         | 
| 1097 | 
            -
                return true
         | 
| 1098 | 
            -
              end
         | 
| 1099 | 
            -
             | 
| 1100 | 
            -
              # => true
         | 
| 1101 | 
            -
              def change_password(user, password)
         | 
| 1102 | 
            -
                params = {'password' => password}
         | 
| 1103 | 
            -
                code, body, res = post("/v3/user/password/change/#{e user}", params)
         | 
| 1104 | 
            -
                if code != "200"
         | 
| 1105 | 
            -
                  raise_error("Changing password failed", res)
         | 
| 1106 | 
            -
                end
         | 
| 1107 | 
            -
                return true
         | 
| 1108 | 
            -
              end
         | 
| 1109 | 
            -
             | 
| 1110 | 
            -
              # => true
         | 
| 1111 | 
            -
              def change_my_password(old_password, password)
         | 
| 1112 | 
            -
                params = {'old_password' => old_password, 'password' => password}
         | 
| 1113 | 
            -
                code, body, res = post("/v3/user/password/change", params)
         | 
| 1114 | 
            -
                if code != "200"
         | 
| 1115 | 
            -
                  raise_error("Changing password failed", res)
         | 
| 1116 | 
            -
                end
         | 
| 1117 | 
            -
                return true
         | 
| 1118 | 
            -
              end
         | 
| 1119 | 
            -
             | 
| 1120 | 
            -
             | 
| 1121 | 
            -
              ####
         | 
| 1122 | 
            -
              ## Access Control API
         | 
| 1123 | 
            -
              ##
         | 
| 1124 | 
            -
             | 
| 1125 | 
            -
              def grant_access_control(subject, action, scope, grant_option)
         | 
| 1126 | 
            -
                params = {'subject'=>subject, 'action'=>action, 'scope'=>scope, 'grant_option'=>grant_option.to_s}
         | 
| 1127 | 
            -
                code, body, res = post("/v3/acl/grant", params)
         | 
| 1128 | 
            -
                if code != "200"
         | 
| 1129 | 
            -
                  raise_error("Granting access control failed", res)
         | 
| 1130 | 
            -
                end
         | 
| 1131 | 
            -
                return true
         | 
| 1132 | 
            -
              end
         | 
| 1133 | 
            -
             | 
| 1134 | 
            -
              def revoke_access_control(subject, action, scope)
         | 
| 1135 | 
            -
                params = {'subject'=>subject, 'action'=>action, 'scope'=>scope}
         | 
| 1136 | 
            -
                code, body, res = post("/v3/acl/revoke", params)
         | 
| 1137 | 
            -
                if code != "200"
         | 
| 1138 | 
            -
                  raise_error("Revoking access control failed", res)
         | 
| 1139 | 
            -
                end
         | 
| 1140 | 
            -
                return true
         | 
| 1141 | 
            -
              end
         | 
| 1142 | 
            -
             | 
| 1143 | 
            -
              # [true, [{subject:String,action:String,scope:String}]]
         | 
| 1144 | 
            -
              def test_access_control(user, action, scope)
         | 
| 1145 | 
            -
                params = {'user'=>user, 'action'=>action, 'scope'=>scope}
         | 
| 1146 | 
            -
                code, body, res = get("/v3/acl/test", params)
         | 
| 1147 | 
            -
                if code != "200"
         | 
| 1148 | 
            -
                  raise_error("Testing access control failed", res)
         | 
| 1149 | 
            -
                end
         | 
| 1150 | 
            -
                js = checked_json(body, %w[permission access_controls])
         | 
| 1151 | 
            -
                perm = js["permission"]
         | 
| 1152 | 
            -
                acl = js["access_controls"].map {|roleinfo|
         | 
| 1153 | 
            -
                  subject = roleinfo['subject']
         | 
| 1154 | 
            -
                  action = roleinfo['action']
         | 
| 1155 | 
            -
                  scope = roleinfo['scope']
         | 
| 1156 | 
            -
                  [name, action, scope]
         | 
| 1157 | 
            -
                }
         | 
| 1158 | 
            -
                return perm, acl
         | 
| 1159 | 
            -
              end
         | 
| 1160 | 
            -
             | 
| 1161 | 
            -
              # [{subject:String,action:String,scope:String}]
         | 
| 1162 | 
            -
              def list_access_controls
         | 
| 1163 | 
            -
                code, body, res = get("/v3/acl/list")
         | 
| 1164 | 
            -
                if code != "200"
         | 
| 1165 | 
            -
                  raise_error("Listing access control failed", res)
         | 
| 1166 | 
            -
                end
         | 
| 1167 | 
            -
                js = checked_json(body, %w[access_controls])
         | 
| 1168 | 
            -
                acl = js["access_controls"].map {|roleinfo|
         | 
| 1169 | 
            -
                  subject = roleinfo['subject']
         | 
| 1170 | 
            -
                  action = roleinfo['action']
         | 
| 1171 | 
            -
                  scope = roleinfo['scope']
         | 
| 1172 | 
            -
                  grant_option = roleinfo['grant_option']
         | 
| 1173 | 
            -
                  [subject, action, scope, grant_option]
         | 
| 1174 | 
            -
                }
         | 
| 1175 | 
            -
                return acl
         | 
| 1176 | 
            -
              end
         | 
| 1177 | 
            -
             | 
| 1178 | 
            -
              ####
         | 
| 1179 | 
            -
              ## Server Status API
         | 
| 1180 | 
            -
              ##
         | 
| 1181 | 
            -
             | 
| 1182 | 
            -
              # => status:String
         | 
| 1183 | 
            -
              def server_status
         | 
| 1184 | 
            -
                code, body, res = get('/v3/system/server_status')
         | 
| 1185 | 
            -
                if code != "200"
         | 
| 1186 | 
            -
                  return "Server is down (#{code})"
         | 
| 1187 | 
            -
                end
         | 
| 1188 | 
            -
                js = checked_json(body, %w[status])
         | 
| 1189 | 
            -
                status = js['status']
         | 
| 1190 | 
            -
                return status
         | 
| 1191 | 
            -
              end
         | 
| 1192 | 
            -
             | 
| 1193 214 | 
             
              def ssl_ca_file=(ssl_ca_file)
         | 
| 1194 215 | 
             
                @ssl_ca_file = ssl_ca_file
         | 
| 1195 216 | 
             
              end
         | 
| 1196 217 |  | 
| 1197 | 
            -
             | 
| 218 | 
            +
            private
         | 
| 219 | 
            +
             | 
| 1198 220 | 
             
              module DeflateReadBodyMixin
         | 
| 1199 221 | 
             
                attr_accessor :gzip
         | 
| 1200 222 |  | 
| @@ -1303,7 +325,6 @@ class API | |
| 1303 325 | 
             
                body = response.body
         | 
| 1304 326 | 
             
                unless block
         | 
| 1305 327 | 
             
                  if ce = response.header['content-encoding']
         | 
| 1306 | 
            -
                    require 'zlib'
         | 
| 1307 328 | 
             
                    if ce == 'gzip'
         | 
| 1308 329 | 
             
                      infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
         | 
| 1309 330 | 
             
                      begin
         | 
| @@ -1377,7 +398,11 @@ class API | |
| 1377 398 | 
             
                      retry_delay *= 2
         | 
| 1378 399 | 
             
                      retry
         | 
| 1379 400 | 
             
                    else
         | 
| 1380 | 
            -
                       | 
| 401 | 
            +
                      if @retry_post_requests
         | 
| 402 | 
            +
                        $stderr.puts "Retrying stopped after #{@max_cumul_retry_delay} seconds."
         | 
| 403 | 
            +
                      else
         | 
| 404 | 
            +
                        $stderr.puts ""
         | 
| 405 | 
            +
                      end
         | 
| 1381 406 | 
             
                      raise e
         | 
| 1382 407 | 
             
                    end
         | 
| 1383 408 | 
             
                  rescue => e
         | 
| @@ -1434,7 +459,7 @@ class API | |
| 1434 459 |  | 
| 1435 460 | 
             
              def build_endpoint(url, host)
         | 
| 1436 461 | 
             
                schema = @ssl ? 'https' : 'http'
         | 
| 1437 | 
            -
                "#{schema}://#{host}:#{@port} | 
| 462 | 
            +
                "#{schema}://#{host}:#{@port}#{@base_path + url}"
         | 
| 1438 463 | 
             
              end
         | 
| 1439 464 |  | 
| 1440 465 | 
             
              def guard_no_sslv3
         | 
| @@ -1543,9 +568,14 @@ class API | |
| 1543 568 | 
             
                # TODO error
         | 
| 1544 569 | 
             
              end
         | 
| 1545 570 |  | 
| 1546 | 
            -
               | 
| 1547 | 
            -
                 | 
| 1548 | 
            -
             | 
| 571 | 
            +
              if ''.respond_to?(:encode)
         | 
| 572 | 
            +
                def e(s)
         | 
| 573 | 
            +
                  CGI.escape(s.to_s.encode("UTF-8"))
         | 
| 574 | 
            +
                end
         | 
| 575 | 
            +
              else
         | 
| 576 | 
            +
                def e(s)
         | 
| 577 | 
            +
                  CGI.escape(s.to_s)
         | 
| 578 | 
            +
                end
         | 
| 1549 579 | 
             
              end
         | 
| 1550 580 |  | 
| 1551 581 | 
             
              def checked_json(body, required)
         | 
| @@ -1568,22 +598,3 @@ class API | |
| 1568 598 | 
             
            end
         | 
| 1569 599 |  | 
| 1570 600 | 
             
            end # module TreasureData
         | 
| 1571 | 
            -
             | 
| 1572 | 
            -
            require 'openssl'
         | 
| 1573 | 
            -
            module OpenSSL
         | 
| 1574 | 
            -
              module SSL
         | 
| 1575 | 
            -
                class SSLContext
         | 
| 1576 | 
            -
             | 
| 1577 | 
            -
                  # For disabling SSLv3 connection in favor of POODLE Attack protection
         | 
| 1578 | 
            -
                  #
         | 
| 1579 | 
            -
                  # Allow 'options' customize through Thread local storage since
         | 
| 1580 | 
            -
                  # Net::HTTP does not support 'options' configuration.
         | 
| 1581 | 
            -
                  #
         | 
| 1582 | 
            -
                  alias original_set_params set_params
         | 
| 1583 | 
            -
                  def set_params(params={})
         | 
| 1584 | 
            -
                    original_set_params(params)
         | 
| 1585 | 
            -
                    self.options |= OP_NO_SSLv3 if Thread.current[:SET_SSL_OP_NO_SSLv3]
         | 
| 1586 | 
            -
                  end
         | 
| 1587 | 
            -
                end
         | 
| 1588 | 
            -
              end
         | 
| 1589 | 
            -
            end
         |