qubole 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 67c203cfa081fa7f902b5f55b9b9525e0ea990a7
4
+ data.tar.gz: 311e01beb229fc56270f5a8272c0c57bdeb25f4e
5
+ SHA512:
6
+ metadata.gz: fb368b40b47aa8d37b6bbb0bc9128228fc93e3a1076da4ff1e7378cd3656992e75fb7036f247411c56faf38197b63b847d8978b0e828a54916a255577e28c24b
7
+ data.tar.gz: 26dedf8fd4b6dde70f6c38ebda6149b5e53c1bf7c314ff68b0d75b35f24e2a2ae24d375f39ed90588f97af61f6a89db0974d137e0cfa06bec1d731095ddacc52
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /vendor/bundle
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ addons:
3
+ code_climate:
4
+ repo_token: 16c4a8ed414d92fe743ce76543d6468fbfedc8e1bfe39c3ba4efc69b026c412c
5
+ rvm:
6
+ - 2.0.0
7
+ - 2.1.0
8
+ - 2.2.0
9
+ script: bundle exec rake
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in qubole.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem "rspec"
8
+ gem "webmock"
9
+ gem 'simplecov', require: false
10
+ gem "codeclimate-test-reporter", require: false
11
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 vladnik
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,125 @@
1
+ # Qubole
2
+
3
+ Qubole REST API client
4
+
5
+ [![Build Status](https://travis-ci.org/Demandbase/qubole-ruby.svg?branch=master)](https://travis-ci.org/Demandbase/qubole-ruby)
6
+ [![Code Climate](https://codeclimate.com/github/Demandbase/qubole/badges/gpa.svg)](https://codeclimate.com/github/Demandbase/qubole)
7
+ [![Test Coverage](https://codeclimate.com/github/Demandbase/qubole/badges/coverage.svg)](https://codeclimate.com/github/Demandbase/qubole/coverage)
8
+
9
+ ## Documentation
10
+
11
+ [API Documentation](http://www.rubydoc.info/github/Demandbase/qubole/master/Qubole)
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'qubole'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install qubole
28
+
29
+ ## Usage
30
+
31
+ require 'qubole'
32
+
33
+ # Configure Qubole with api_token and optional API version
34
+ Qubole.configure(api_token: 'ksbdvcwdkjn123423', version: 'v1.2')
35
+
36
+ # Submit Command
37
+ command = Qubole::Commands::Hive.new
38
+ command.submit(query: "SHOW TABLES", label: "custom cluster")
39
+ command.status # => "waiting"
40
+ command.refresh!
41
+ command.status # => "done"
42
+ command.results # => {"results"=>"default_qubole_airline_origin_destination\r\ndefault_qubole_memetracker\r\n", "inline"=>true}
43
+ id = command.id
44
+ command = Qubole::Command.find(id)
45
+ command.logs # => "OK\n Time taken: 3.017 seconds, Fetched: 2 row(s)"
46
+
47
+ ## Implemented
48
+
49
+ [Qubole REST API](http://docs.qubole.com/en/latest/rest-api/index.html) version v1.2
50
+
51
+ - [x] Authentication
52
+ - [x] Command API
53
+ - [x] Submit a Command
54
+ - [x] View Command Status
55
+ - [x] View Command Results
56
+ - [x] View Command Logs
57
+ - [x] View Hadoop Jobs Spawned By a Command
58
+ - [x] Cancel a Command
59
+ - [x] View Command History
60
+ - [x] Composite Command
61
+ - [x] DB Export Command
62
+ - [x] DB Import Command
63
+ - [x] DB Tap Query Command
64
+ - [x] Hadoop Jar Command
65
+ - [x] Hive Command
66
+ - [x] Pig Command
67
+ - [x] Presto Command
68
+ - [x] Shell Command
69
+ - [x] Spark Command
70
+ - [ ] Hive Metadata API
71
+ - [ ] List Tables
72
+ - [ ] Get Table Definition
73
+ - [ ] Get Table Properties
74
+ - [ ] Store Table Properties
75
+ - [ ] Delete Table Properties
76
+ - [ ] DbTap API
77
+ - [ ] List DbTaps
78
+ - [ ] View a DbTap
79
+ - [ ] List Tables in a DbTap
80
+ - [ ] Create a DbTap
81
+ - [ ] Edit a DbTap
82
+ - [ ] Delete a DbTap
83
+ - [ ] Scheduler API
84
+ - [ ] List Schedules
85
+ - [ ] View a Schedule
86
+ - [ ] Create a Schedule
87
+ - [ ] Suspend,Resume or Kill a Schedule
88
+ - [ ] List Schedule Actions
89
+ - [ ] View a Schedule’s Action
90
+ - [ ] Kill a Schedule Action
91
+ - [ ] Rerun a Scheduled Action
92
+ - [ ] List All Actions
93
+ - [ ] View an Action
94
+ - [ ] Reports API
95
+ - [ ] All Commands Report
96
+ - [ ] Canonical Hive Commands Report
97
+ - [ ] Cluster nodes Report
98
+ - [ ] Cluster API
99
+ - [ ] List All Clusters
100
+ - [ ] Create a New Cluster
101
+ - [ ] View Cluster Configuration
102
+ - [ ] Edit Cluster Configuration
103
+ - [ ] Clone a Cluster
104
+ - [ ] Start or Terminate a Cluster
105
+ - [ ] Check Cluster Status
106
+ - [ ] Delete a Cluster
107
+ - [ ] Reassign Cluster Label
108
+ - [ ] Run Adhoc Scripts on a Cluster
109
+ - [ ] Cluster Metrics
110
+ - [ ] Add a Node to a Cluster
111
+ - [ ] Replace a Node in a Cluster
112
+ - [ ] Remove a Node from a Cluster
113
+ - [ ] Take an HBase Snapshot
114
+ - [ ] View an HBase Snapshot Schedule
115
+ - [ ] Restore HBase Tables
116
+ - [ ] Update an HBase Snapshot Schedule
117
+
118
+
119
+ ## Contributing
120
+
121
+ 1. Fork it ( https://github.com/[my-github-username]/qubole/fork )
122
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
123
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
124
+ 4. Push to the branch (`git push origin my-new-feature`)
125
+ 5. Create a new Pull Request
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task default: :spec
@@ -0,0 +1,85 @@
1
+ require "qubole/version"
2
+ require "qubole/exceptions"
3
+ require "qubole/commands"
4
+ require "net/http"
5
+ require "json"
6
+
7
+ module Qubole
8
+ ACCESS_URL = 'https://api.qubole.com/api/'
9
+ API_VERSION = 'v1.2'
10
+
11
+ class << self
12
+ attr_accessor :api_token, :version
13
+
14
+ #
15
+ # API version
16
+ #
17
+ # @return [String] API version used
18
+ def version
19
+ @version || API_VERSION
20
+ end
21
+
22
+ #
23
+ # Configure Qubole
24
+ # @param params [Hash] configuration parameters
25
+ # @option params [String] :api_token Qubole API token
26
+ # @option params [String] :version Qubole API version (v1.2 be default)
27
+ #
28
+ def configure(params)
29
+ self.api_token = params[:api_token]
30
+ self.version = params[:version]
31
+ end
32
+
33
+ #
34
+ # Request headers
35
+ #
36
+ # @return [Hash] request headers
37
+ def headers
38
+ {
39
+ 'Content-Type' => 'application/json',
40
+ 'Accept' => 'application/json',
41
+ 'X-AUTH-TOKEN' => @api_token
42
+ }
43
+ end
44
+
45
+ #
46
+ # HTTP request to Qubole
47
+ # @param path [String] API path
48
+ # @param params [Hash] GET parameters
49
+ # @yieldparam [Net::HTTP] http HTTP connection
50
+ # @yieldparam [URI] uri request URI
51
+ #
52
+ # @return [Hash|Array] parsed JSON response
53
+ def http(name, path, params)
54
+ # Build URI
55
+ uri = URI(ACCESS_URL + version)
56
+ uri.path += path
57
+
58
+ # Encode parameters for GET request
59
+ if name == 'GET'
60
+ uri.query = URI.encode_www_form(params)
61
+ else
62
+ # Stringify JSON for all other requests
63
+ data = JSON.generate(params) unless params.empty?
64
+ end
65
+
66
+ # Open connection
67
+ res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
68
+ # Execute request
69
+ http.send_request(name, uri, data, headers)
70
+ end
71
+
72
+ # Raise error message if not success
73
+ raise HttpException.new(res) unless res.is_a? Net::HTTPSuccess
74
+ # Parse JSON body
75
+ JSON.parse(res.body) rescue res.body
76
+ end
77
+
78
+ # Defining HTTP methods for Qubole
79
+ %w(get post put delete).each do |name|
80
+ define_method(name) do |path, params = {}|
81
+ http(name.upcase, path, params)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,91 @@
1
+ require "ostruct"
2
+
3
+ module Qubole
4
+ class Command < OpenStruct
5
+ #
6
+ # Paginated commands history
7
+ # @param page [Integer] page number
8
+ # @param [Hash] opts addional options
9
+ # @option attrs [String] :per_page results per page
10
+ #
11
+ # @return [Array<Command>] paginated commands
12
+ def self.page(page, opts = {})
13
+ per_page = opts[:per_page] || 10
14
+ Qubole.get('/commands', page: page, per_page: per_page)['commands'].map do |command|
15
+ new(command)
16
+ end
17
+ end
18
+
19
+ #
20
+ # Find command by id
21
+ # @param id [Integer] command id
22
+ #
23
+ # @return [Command] command instance
24
+ def self.find(id)
25
+ command = Qubole.get("/commands/#{id}")
26
+ new(command)
27
+ end
28
+
29
+ #
30
+ # Update command attributes
31
+ # @param attrs [Hash] command attributes
32
+ #
33
+ # @return [Command] command instance
34
+ def parse(attrs)
35
+ attrs.each do |key, value|
36
+ send("#{key}=", value)
37
+ end
38
+ end
39
+
40
+ #
41
+ # Submit command to Qubole
42
+ # @param params [Hash] command payload
43
+ #
44
+ # @return [Command] command instance
45
+ def submit(params = {})
46
+ parse(params)
47
+ response = Qubole.post('/commands', self.to_h)
48
+ parse(response)
49
+ end
50
+
51
+ #
52
+ # Refresh command attributes
53
+ #
54
+ # @return [Command] command instance
55
+ def refresh!
56
+ command = Qubole.get("/commands/#{id}")
57
+ parse(command)
58
+ end
59
+
60
+ #
61
+ # Fetch command results
62
+ #
63
+ # @return [Hash] parsed JSON response
64
+ def results
65
+ Qubole.get("/commands/#{id}/results")
66
+ end
67
+
68
+ #
69
+ # Fetch command logs
70
+ #
71
+ # @return [String] command logs
72
+ def logs
73
+ Qubole.get("/commands/#{id}/logs")
74
+ end
75
+
76
+ #
77
+ # Hadoop jobs spawned by command
78
+ #
79
+ # @return [Hash] parsed JSON response
80
+ def jobs
81
+ Qubole.get("/commands/#{id}/jobs")
82
+ end
83
+
84
+ #
85
+ # Cancel command
86
+ #
87
+ def cancel
88
+ Qubole.put("/commands/#{id}")
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,10 @@
1
+ require 'qubole/commands/composite'
2
+ require 'qubole/commands/db_export'
3
+ require 'qubole/commands/db_import'
4
+ require 'qubole/commands/db_tap_query'
5
+ require 'qubole/commands/hadoop'
6
+ require 'qubole/commands/hive'
7
+ require 'qubole/commands/pig'
8
+ require 'qubole/commands/presto'
9
+ require 'qubole/commands/shell'
10
+ require 'qubole/commands/spark'
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class Composite < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'CompositeCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class DbExport < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'DbExportCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class DbImport < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'DbImportCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class DbTapQuery < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'DbTapQueryCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class Hadoop < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'HadoopCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class Hive < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'HiveCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class Pig < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'PigCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class Presto < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'PrestoCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class Shell < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'ShellCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'qubole/command'
2
+
3
+ module Qubole
4
+ module Commands
5
+ class Spark < Command
6
+ def initialize(attrs = {})
7
+ attrs[:command_type] = 'SparkCommand'
8
+ super(attrs)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Qubole
2
+ class HttpException < StandardError
3
+ attr :body
4
+ def initialize(object)
5
+ @body = object.body
6
+ super(object.message)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Qubole
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'qubole/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "qubole"
8
+ spec.version = Qubole::VERSION
9
+ spec.authors = ["Volodymyr Ladnik"]
10
+ spec.email = ["vladnik@demandbase.com"]
11
+ spec.summary = %q{Qubole REST API client}
12
+ spec.description = %q{Communication with Qubole REST API in a Ruby way}
13
+ spec.homepage = "https://github.com/Demandbase/qubole"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ end
@@ -0,0 +1,77 @@
1
+ module Qubole
2
+ describe Command do
3
+ subject { Command.new(id: 1) }
4
+
5
+ describe "::page" do
6
+ it "returns array of commands" do
7
+ attrs = {id: 1, name: 'Fake'}
8
+ expect(Qubole).to receive(:get).with("/commands", {page: 1, per_page: 10}).and_return('commands' => [attrs])
9
+ expect(Command.page(1)).to eq([Qubole::Command.new(attrs)])
10
+ end
11
+ end
12
+
13
+ describe "::find" do
14
+ it "returns command by id" do
15
+ attrs = {id: 1, name: 'Fake'}
16
+ expect(Qubole).to receive(:get).with("/commands/1").and_return(attrs)
17
+ expect(Command.find(1)).to eq(Qubole::Command.new(attrs))
18
+ end
19
+ end
20
+
21
+ describe "#parse" do
22
+ it "updates command attributes" do
23
+ subject.parse(id: 2, name: 'Fake')
24
+ expect(subject.id).to eq(2)
25
+ expect(subject.name).to eq('Fake')
26
+ end
27
+ end
28
+
29
+ describe "#submit" do
30
+ it "sends command to Qubole and updates attributes" do
31
+ expect(Qubole).to receive(:post).with("/commands", id: 1, query:"SHOW TABLES", label: "custom cluster").and_return(id: 10, status: 'waiting')
32
+ subject.submit(query: "SHOW TABLES", label: "custom cluster")
33
+ expect(subject.id).to eq(10)
34
+ expect(subject.status).to eq('waiting')
35
+ end
36
+ end
37
+
38
+ describe "#refresh!" do
39
+ it "refreshes command attributes" do
40
+ expect(Qubole).to receive(:get).with("/commands/1").and_return(status: 'waiting')
41
+ subject.refresh!
42
+ expect(subject.status).to eq('waiting')
43
+ end
44
+ end
45
+
46
+ describe "#results" do
47
+ it "fetches results from Qubole" do
48
+ results = {"results"=>"data", "inline"=>true}
49
+ expect(Qubole).to receive(:get).with("/commands/1/results").and_return(results)
50
+ expect(subject.results).to eq(results)
51
+ end
52
+ end
53
+
54
+ describe "#logs" do
55
+ it "fetches logs from Qubole" do
56
+ logs = "some logs"
57
+ expect(Qubole).to receive(:get).with("/commands/1/logs").and_return(logs)
58
+ expect(subject.logs).to eq(logs)
59
+ end
60
+ end
61
+
62
+ describe "#jobs" do
63
+ it "fetches Hadoop jobs spawned by command" do
64
+ jobs = [{"job_id"=>"job_2588.201506291819_0018"}]
65
+ expect(Qubole).to receive(:get).with("/commands/1/jobs").and_return(jobs)
66
+ expect(subject.jobs).to eq(jobs)
67
+ end
68
+ end
69
+
70
+ describe "#cancel" do
71
+ it "cancels command execution" do
72
+ expect(Qubole).to receive(:put).with("/commands/1")
73
+ subject.cancel
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe Composite do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::Composite.new
6
+ command.command_type = 'CompositeCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe DbExport do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::DbExport.new
6
+ command.command_type = 'DbExportCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe DbImport do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::DbImport.new
6
+ command.command_type = 'DbImportCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe DbTapQuery do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::DbTapQuery.new
6
+ command.command_type = 'DbTapQueryCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe Hadoop do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::Hadoop.new
6
+ command.command_type = 'HadoopCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe Hive do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::Hive.new
6
+ command.command_type = 'HiveCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe Pig do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::Pig.new
6
+ command.command_type = 'PigCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe Presto do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::Presto.new
6
+ command.command_type = 'PrestoCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe Shell do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::Shell.new
6
+ command.command_type = 'ShellCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Qubole::Commands
2
+ describe Spark do
3
+ describe "initialize" do
4
+ it "sets correct command type" do
5
+ command = Qubole::Commands::Spark.new
6
+ command.command_type = 'SparkCommand'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module Qubole
2
+ describe HttpException do
3
+ before(:each) do
4
+ Qubole.configure(api_token: 'ksbdvcwdkjn123423')
5
+ end
6
+
7
+ it "returns array of commands" do
8
+ stub_request(:get, "https://api.qubole.com/api/v1.2/fake_path").to_return(status: 400)
9
+ expect{ Qubole.get('/fake_path') }.to raise_error(Qubole::HttpException)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,52 @@
1
+ describe Qubole do
2
+ before(:each) do
3
+ Qubole.configure(api_token: 'ksbdvcwdkjn123423')
4
+ end
5
+
6
+ describe "::configure" do
7
+ it "sets Qubole configuration" do
8
+ Qubole.configure(api_token: '123', version: 'latest')
9
+ expect(Qubole.api_token).to eq('123')
10
+ expect(Qubole.version).to eq('latest')
11
+ end
12
+ end
13
+
14
+ describe "::get" do
15
+ context "without parameters" do
16
+ it "sends GET request to Qubole and parses response" do
17
+ stub_request(:get, "https://api.qubole.com/api/v1.2/fake_path")
18
+ .to_return(status: 200, body: '{"result": "ok"}')
19
+ expect(Qubole.get('/fake_path')).to eq('result'=>'ok')
20
+ end
21
+
22
+ it "sends GET request and doesn't fail on raw response" do
23
+ stub_request(:get, "https://api.qubole.com/api/v1.2/fake_path")
24
+ .to_return(status: 200, body: "raw data")
25
+ expect(Qubole.get('/fake_path')).to eq("raw data")
26
+ end
27
+ end
28
+ context "with parameters" do
29
+ it "sends GET request to Qubole with encoded parameters" do
30
+ stub_request(:get, "https://api.qubole.com/api/v1.2/fake_path?name=John%20Doe")
31
+ .to_return(status: 200, body: '{"result": "ok"}')
32
+ expect(Qubole.get('/fake_path', name: 'John Doe')).to eq('result'=>'ok')
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "::post" do
38
+ it "encodes data and parses response" do
39
+ stub_request(:post, "https://api.qubole.com/api/v1.2/fake_path").with(body: '{"data":"ok"}')
40
+ .to_return(status: 200, body: '{"result": "ok"}')
41
+ expect(Qubole.post('/fake_path', {data: :ok})).to eq('result'=>'ok')
42
+ end
43
+ end
44
+
45
+ describe "::delete" do
46
+ it "works with empty data" do
47
+ stub_request(:delete, "https://api.qubole.com/api/v1.2/fake_path")
48
+ .to_return(status: 200, body: '{"result": "ok"}')
49
+ expect(Qubole.delete('/fake_path')).to eq('result'=>'ok')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,109 @@
1
+ require 'webmock/rspec'
2
+ require 'simplecov'
3
+ require "codeclimate-test-reporter"
4
+ CodeClimate::TestReporter.start
5
+
6
+ SimpleCov.start do
7
+ add_filter '/spec/'
8
+ add_filter '/vendor/'
9
+ end
10
+ require 'qubole'
11
+
12
+ # This file was generated by the `rspec --init` command. Conventionally, all
13
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
14
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
15
+ # this file to always be loaded, without a need to explicitly require it in any
16
+ # files.
17
+ #
18
+ # Given that it is always loaded, you are encouraged to keep this file as
19
+ # light-weight as possible. Requiring heavyweight dependencies from this file
20
+ # will add to the boot time of your test suite on EVERY test run, even for an
21
+ # individual file that may not need all of that loaded. Instead, consider making
22
+ # a separate helper file that requires the additional dependencies and performs
23
+ # the additional setup, and require it from the spec files that actually need
24
+ # it.
25
+ #
26
+ # The `.rspec` file also contains a few flags that are not defaults but that
27
+ # users commonly want.
28
+ #
29
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
30
+ WebMock.allow_net_connect!(net_http_connect_on_start: true)
31
+
32
+ RSpec.configure do |config|
33
+ # rspec-expectations config goes here. You can use an alternate
34
+ # assertion/expectation library such as wrong or the stdlib/minitest
35
+ # assertions if you prefer.
36
+ config.expect_with :rspec do |expectations|
37
+ # This option will default to `true` in RSpec 4. It makes the `description`
38
+ # and `failure_message` of custom matchers include text for helper methods
39
+ # defined using `chain`, e.g.:
40
+ # be_bigger_than(2).and_smaller_than(4).description
41
+ # # => "be bigger than 2 and smaller than 4"
42
+ # ...rather than:
43
+ # # => "be bigger than 2"
44
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
45
+ end
46
+
47
+ # rspec-mocks config goes here. You can use an alternate test double
48
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
49
+ config.mock_with :rspec do |mocks|
50
+ # Prevents you from mocking or stubbing a method that does not exist on
51
+ # a real object. This is generally recommended, and will default to
52
+ # `true` in RSpec 4.
53
+ mocks.verify_partial_doubles = true
54
+ end
55
+
56
+ # The settings below are suggested to provide a good initial experience
57
+ # with RSpec, but feel free to customize to your heart's content.
58
+ =begin
59
+ # These two settings work together to allow you to limit a spec run
60
+ # to individual examples or groups you care about by tagging them with
61
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
62
+ # get run.
63
+ config.filter_run :focus
64
+ config.run_all_when_everything_filtered = true
65
+
66
+ # Allows RSpec to persist some state between runs in order to support
67
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
68
+ # you configure your source control system to ignore this file.
69
+ config.example_status_persistence_file_path = "spec/examples.txt"
70
+
71
+ # Limits the available syntax to the non-monkey patched syntax that is
72
+ # recommended. For more details, see:
73
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
74
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
75
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
76
+ config.disable_monkey_patching!
77
+
78
+ # This setting enables warnings. It's recommended, but in some cases may
79
+ # be too noisy due to issues in dependencies.
80
+ config.warnings = true
81
+
82
+ # Many RSpec users commonly either run the entire suite or an individual
83
+ # file, and it's useful to allow more verbose output when running an
84
+ # individual spec file.
85
+ if config.files_to_run.one?
86
+ # Use the documentation formatter for detailed output,
87
+ # unless a formatter has already been configured
88
+ # (e.g. via a command-line flag).
89
+ config.default_formatter = 'doc'
90
+ end
91
+
92
+ # Print the 10 slowest examples and example groups at the
93
+ # end of the spec run, to help surface which specs are running
94
+ # particularly slow.
95
+ config.profile_examples = 10
96
+
97
+ # Run specs in random order to surface order dependencies. If you find an
98
+ # order dependency and want to debug it, you can fix the order by providing
99
+ # the seed, which is printed after each run.
100
+ # --seed 1234
101
+ config.order = :random
102
+
103
+ # Seed global randomization in this process using the `--seed` CLI option.
104
+ # Setting this allows you to use `--seed` to deterministically reproduce
105
+ # test failures related to randomization by passing the same `--seed` value
106
+ # as the one that triggered the failure.
107
+ Kernel.srand config.seed
108
+ =end
109
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qubole
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Volodymyr Ladnik
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10.0'
27
+ description: Communication with Qubole REST API in a Ruby way
28
+ email:
29
+ - vladnik@demandbase.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - ".rspec"
36
+ - ".travis.yml"
37
+ - Gemfile
38
+ - LICENSE.txt
39
+ - README.md
40
+ - Rakefile
41
+ - lib/qubole.rb
42
+ - lib/qubole/command.rb
43
+ - lib/qubole/commands.rb
44
+ - lib/qubole/commands/composite.rb
45
+ - lib/qubole/commands/db_export.rb
46
+ - lib/qubole/commands/db_import.rb
47
+ - lib/qubole/commands/db_tap_query.rb
48
+ - lib/qubole/commands/hadoop.rb
49
+ - lib/qubole/commands/hive.rb
50
+ - lib/qubole/commands/pig.rb
51
+ - lib/qubole/commands/presto.rb
52
+ - lib/qubole/commands/shell.rb
53
+ - lib/qubole/commands/spark.rb
54
+ - lib/qubole/exceptions.rb
55
+ - lib/qubole/version.rb
56
+ - qubole.gemspec
57
+ - spec/qubole/command_spec.rb
58
+ - spec/qubole/commands/composite_spec.rb
59
+ - spec/qubole/commands/db_export_spec.rb
60
+ - spec/qubole/commands/db_import_spec.rb
61
+ - spec/qubole/commands/db_tap_query_spec.rb
62
+ - spec/qubole/commands/hadoop_spec.rb
63
+ - spec/qubole/commands/hive_spec.rb
64
+ - spec/qubole/commands/pig_spec.rb
65
+ - spec/qubole/commands/presto_spec.rb
66
+ - spec/qubole/commands/shell_spec.rb
67
+ - spec/qubole/commands/spark_spec.rb
68
+ - spec/qubole/exceptions_spec.rb
69
+ - spec/qubole_spec.rb
70
+ - spec/spec_helper.rb
71
+ homepage: https://github.com/Demandbase/qubole
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.2.2
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Qubole REST API client
95
+ test_files:
96
+ - spec/qubole/command_spec.rb
97
+ - spec/qubole/commands/composite_spec.rb
98
+ - spec/qubole/commands/db_export_spec.rb
99
+ - spec/qubole/commands/db_import_spec.rb
100
+ - spec/qubole/commands/db_tap_query_spec.rb
101
+ - spec/qubole/commands/hadoop_spec.rb
102
+ - spec/qubole/commands/hive_spec.rb
103
+ - spec/qubole/commands/pig_spec.rb
104
+ - spec/qubole/commands/presto_spec.rb
105
+ - spec/qubole/commands/shell_spec.rb
106
+ - spec/qubole/commands/spark_spec.rb
107
+ - spec/qubole/exceptions_spec.rb
108
+ - spec/qubole_spec.rb
109
+ - spec/spec_helper.rb