xplenty-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ /.idea
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+
3
+ notifications:
4
+ email: false
5
+
6
+ rvm:
7
+ - 1.8.7
8
+ - 1.9.2
9
+ - 1.9.3
10
+
11
+ script: bundle exec rake
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in xplenty.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ xplenty-api (0.0.1)
5
+ excon (~> 0.20.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ excon (0.20.1)
11
+ minitest (4.7.4)
12
+ rake (10.0.4)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ minitest
19
+ rake
20
+ xplenty-api!
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2012-2013 Xplenty, Ltd. http://www.xplenty.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,139 @@
1
+ ## Xplenty Ruby Wrapper
2
+
3
+ [![Build Status](https://travis-ci.org/xplenty/xplenty.rb.png)](https://travis-ci.org/xplenty/xplenty.rb)
4
+
5
+ The Xplenty rb is a Ruby artifact that provides a simple wrapper for the [Xplenty REST Api](https://github.com/xplenty/xplenty-api-doc).
6
+ To use it, create an TODO:OBJECT-NAME object and call its methods to access the Xplenty API.
7
+ This page describes the available XplentyAPI methods.
8
+
9
+ ### Create an XplentyAPI Object
10
+
11
+ Pass your account ID and API key to the XplentyAPI constructor.
12
+ ```ruby
13
+ @xplenty = Xplenty::API.new(:api_key => 'your_api_key', :account_id => 'your_account_id')
14
+ ```
15
+ If you want to supply custom values for the version, scheme or host that the Xplenty::API object will use,
16
+ you can use Xplenty::API builder methods to customize these properties.
17
+ ```ruby
18
+ @xplenty = Xplenty::API.new(:api_key => 'your_api_key', :account_id => 'your_account_id', :scheme => 'https', :host => 'api.xplenty.com')
19
+ @xplenty = Xplenty::API.new(:api_key => 'your_api_key', :account_id => 'your_account_id', :headers => { 'User-Agent' => 'your user agent' })
20
+ TODO:INSERT-CODE
21
+ ```
22
+ ### List the Cluster Plans
23
+
24
+ A cluster plan is a definition of a cluster type, which includes the number of nodes in the cluster and its pricing. Cluster plan details can be viewed in the Xplenty web application.
25
+ After you've determined which cluster plan is appropriate for your needs, use this method to retrieve the cluster plan ID. The cluster plan ID can then be used when creating a new cluster.
26
+ ```ruby
27
+ @xplenty.cluster_plans
28
+ ```
29
+ ### Create a Cluster
30
+
31
+ This method creates a new cluster. A cluster is a group of machines ("nodes") allocated to your account. The number of nodes in the cluster is determined by the "plan_id" value that you supply to the call. While the cluster is active, only your account's users can run jobs on the cluster.
32
+ You will need to provide an active cluster when starting a new job. Save the cluster ID value returned in the response "id" field. You will use the value to refer to this cluster in subsequent API calls.
33
+ ```ruby
34
+ @xplenty.create_cluster(:nodes => 1, :type => "sandbox")
35
+ ```
36
+ ### List All Clusters
37
+
38
+ This method returns the list of clusters that were created by users in your account.
39
+ You can use this information to monitor and display your clusters and their statuses.
40
+
41
+ ```ruby
42
+ @xplenty.clusters # return all clusters
43
+ ```
44
+ XplentyAPI.listClusters() is shorthand for XplentyAPI.listClusters(new Properties()), which returns all clusters with no filtering.
45
+ You can also pass property parameters which filter the clusters according to their status, and determine the order in which they'll be sorted.
46
+ Only clusters which have the status passed in the PARAMETER_STATUS property will be returned, sorted according to the field passed in PARAMETER_SORT,
47
+ in ascending or descending order according to the PARAMETER_DIRECTION property.
48
+
49
+ ```ruby
50
+ @xplenty.clusters(:status => 'terminated')
51
+ @xplenty.clusters(:sort => 'created', :direction => 'desc')
52
+ ```
53
+ ### Get Cluster Information
54
+
55
+ This method returns the details of the cluster with the given ID.
56
+ ```ruby
57
+ @xplenty.get_cluster_info(1792)
58
+ ```
59
+ ### Terminate a Cluster
60
+
61
+ This method deactivates the given cluster, releasing its resources and terminating its runtime period. Use this method when all of the cluster's jobs are completed and it's no longer needed. The method returns the given cluster's details, including a status of "pending_terminate".
62
+ ```ruby
63
+ @xplenty.terminate_cluster(1792)
64
+ ```
65
+ ### Run a Job
66
+
67
+ This method creates a new job and triggers it to run. The job performs the series of data processing tasks that are defined in the job's package. Unless the job encounters an error or is terminated by the user, it will run until it completes its tasks on all of the input data. Save the job ID value returned in the response "id" field. You will use the value to refer to this job in subsequent API calls.
68
+ ```ruby
69
+ @xplenty.run_job(1792, 902, {:first_arg => 'Argument 1'})
70
+ ```
71
+ ### List All Jobs
72
+
73
+ This method returns information for all the jobs that have been created under your account.
74
+ ```ruby
75
+ @xplenty.jobs
76
+ ```
77
+ XplentyAPI.listJobs() is shorthand for XplentyAPI.listJobs(new Properties()), which returns all jobs with no filtering.
78
+ You can also pass property parameters which filter the jobs according to their status, and determine the order in which they'll be sorted.
79
+ Only jobs which have the status passed in the PARAMETER_STATUS property will be returned, sorted according to the field passed in PARAMETER_SORT,
80
+ in ascending or descending order according to the PARAMETER_DIRECTION property.
81
+ ```ruby
82
+ @xplenty.jobs(:status => 'idle')
83
+ @xplenty.jobs(:status => 'completed', :sort => 'created_at', :direction => 'asc')
84
+ ```
85
+
86
+ ### Get Job Information
87
+
88
+ This method retrieves information for a job, according to the given job ID.
89
+ ```ruby
90
+ @xplenty.get_job_info(9032)
91
+ ```
92
+ ### Terminate a Job
93
+
94
+ This method terminates an active job. Usually it's unnecessary to request to terminate a job, because normally the job will end when its tasks are completed. You may want to actively terminate a job if you need its cluster resources for a more urgent job, or if the job is taking too long to complete.
95
+ ```ruby
96
+ @xplenty.terminate_job(9032)
97
+ ```
98
+ ### Watch Cluster
99
+
100
+ You can watch a cluster that you or others have created. If you'r watching a cluster, you'll receive notifications (email messages or web notifications) on important updates.
101
+
102
+ This method adds the calling user as a watcher of the specifeid cluster.
103
+ ```ruby
104
+ @xplenty.watch_cluster(1792)
105
+ ```
106
+ ### Stop Watching Cluster
107
+
108
+ This method removes the calling user from the watcher list of the specified cluster.
109
+ ```ruby
110
+ @xplenty.stop_watching_cluster(1792)
111
+ ```
112
+ ### Get Cluster Watchers
113
+
114
+ This call retrieves the list of users watching the specified cluster.
115
+ ```ruby
116
+ @xplenty.cluster_watchers(1792)
117
+ ```
118
+ ### Watch Job
119
+
120
+ You can watch a job that you or others have executed. If you'r watching a job, you'll receive notifications (email messages or web notifications) on important updates.
121
+
122
+ This method adds the calling user as a watcher of the specifeid job.
123
+ ```ruby
124
+ @xplenty.watch_job(9032)
125
+ ```
126
+ ### Stop Watching Job
127
+
128
+ This method removes the calling user from the watcher list of the specified job.
129
+ ```ruby
130
+ @xplenty.stop_watching_job(9032)
131
+ ```
132
+ ### Get Job Watchers
133
+
134
+ This call retrieves the list of users watching the specified job.
135
+ ```ruby
136
+ @xplenty.job_watchers(9032)
137
+ ```
138
+ ## License
139
+ Released under the [MIT license](http://www.opensource.org/licenses/mit-license.php).
@@ -0,0 +1,29 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new do |task|
8
+ task.name = :test
9
+ task.test_files = FileList['test/test*.rb']
10
+ end
11
+
12
+ task :cache, [:account_id, :api_key] do |task, args|
13
+ unless args.api_key && args.account_id
14
+ puts('cache requires an account id and api key, please call as `cache[account_id api_key]`')
15
+ else
16
+ require "#{File.dirname(__FILE__)}/lib/xplenty/api"
17
+ xplenty = Xplenty::API.new(:api_key => args.api_key, :account_id => args.account_id)
18
+
19
+ clusters = Xplenty::API::OkJson.encode(xplenty.clusters.body)
20
+ File.open("#{File.dirname(__FILE__)}/lib/xplenty/api/mock/cache/clusters.json", 'w') do |file|
21
+ file.write(clusters)
22
+ end
23
+
24
+ jobs = Xplenty::API::OkJson.encode(xplenty.jobs.body)
25
+ File.open("#{File.dirname(__FILE__)}/lib/xplenty/api/mock/cache/jobs.json", 'w') do |file|
26
+ file.write(jobs)
27
+ end
28
+ end
29
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require(File.join(File.dirname(__FILE__), "xplenty", "api"))
@@ -0,0 +1,107 @@
1
+ require "base64"
2
+ require "excon"
3
+ require "securerandom"
4
+ require "uri"
5
+ require "zlib"
6
+
7
+ __LIB_DIR__ = File.expand_path(File.join(File.dirname(__FILE__), ".."))
8
+ unless $LOAD_PATH.include?(__LIB_DIR__)
9
+ $LOAD_PATH.unshift(__LIB_DIR__)
10
+ end
11
+
12
+ require "xplenty/api/vendor/okjson"
13
+
14
+ require "xplenty/api/errors"
15
+ require "xplenty/api/mock"
16
+ require "xplenty/api/version"
17
+
18
+ require "xplenty/api/jobs"
19
+ require "xplenty/api/cluster_plans"
20
+ require "xplenty/api/clusters"
21
+ require "xplenty/api/watchers"
22
+
23
+ srand
24
+
25
+ module Xplenty
26
+ class API
27
+
28
+ HEADERS = {
29
+ 'Accept' => 'application/vnd.xplenty+json'
30
+ }
31
+
32
+ OPTIONS = {
33
+ :headers => {},
34
+ :host => 'api.xplenty.com',
35
+ :nonblock => false,
36
+ :scheme => 'https'
37
+ }
38
+
39
+ def initialize(options={})
40
+ options = OPTIONS.merge(options)
41
+
42
+ @api_key = options.delete(:api_key) || ENV['XPLENTY_API_KEY']
43
+ @account_id = options.delete(:account_id) || ENV['XPLENTY_ACCOUNT_ID']
44
+ @version = options.delete(:version)
45
+ @mime_type = "application/vnd.xplenty+json"
46
+ if @version && @version.is_a?(Fixnum)
47
+ @mime_type = @mime_type << "; version=#{@version}"
48
+ end
49
+ user_name = "#{@api_key}"
50
+ options[:headers] = HEADERS.merge({
51
+ 'Authorization' => "Basic #{Base64.encode64(user_name).gsub("\n", '')}",
52
+ 'Accept' => @mime_type
53
+ }).merge(options[:headers])
54
+
55
+ @connection = Excon.new("#{options[:scheme]}://#{options[:host]}", options)
56
+ end
57
+
58
+ def request(params, &block)
59
+ begin
60
+ response = @connection.request(params, &block)
61
+ rescue Excon::Errors::HTTPStatusError => error
62
+ klass = case error.response.status
63
+ when 400 then Xplenty::API::Errors::BadRequest
64
+ when 401 then Xplenty::API::Errors::Unauthorized
65
+ when 402 then Xplenty::API::Errors::PaymentRequired
66
+ when 403 then Xplenty::API::Errors::Forbidden
67
+ when 404 then Xplenty::API::Errors::NotFound
68
+ when 406 then Xplenty::API::Errors::NotAcceptable
69
+ when 415 then Xplenty::API::Errors::UnsupportedMediaType
70
+ when 422 then Xplenty::API::Errors::UnprocessableEntity
71
+ when 429 then Xplenty::API::Errors::TooManyRequests
72
+ when 500 then Xplenty::API::Errors::RequestFailed
73
+ when 502 then Xplenty::API::Errors::BadGateway
74
+ when 503 then Xplenty::API::Errors::ServiceUnavailable
75
+ else Xplenty::API::Errors::ErrorWithResponse
76
+ end
77
+
78
+ reerror = klass.new(error.message, error.response)
79
+ reerror.set_backtrace(error.backtrace)
80
+ raise(reerror)
81
+ end
82
+
83
+ if response.body && !response.body.empty?
84
+ if response.headers['Content-Encoding'] == 'gzip'
85
+ response.body = Zlib::GzipReader.new(StringIO.new(response.body)).read
86
+ end
87
+ begin
88
+ response.body = Xplenty::API::OkJson.decode(response.body)
89
+ #rescue
90
+ # leave non-JSON body as is
91
+ end
92
+ end
93
+
94
+ # reset (non-persistent) connection
95
+ @connection.reset
96
+
97
+ response
98
+ end
99
+
100
+ private
101
+
102
+ def account_id
103
+ @account_id
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,12 @@
1
+ module Xplenty
2
+ class API
3
+ # GET /<accountID>/api/cluster_plans
4
+ def cluster_plans
5
+ request(
6
+ :expects => 200,
7
+ :method => :get,
8
+ :path => "/#{account_id}/api/cluster_plans"
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ module Xplenty
2
+ class API
3
+ # POST /<accountID>/api/clusters
4
+ def create_cluster(cluster_info)
5
+ cluster_info = cluster_info.inject({}) { |v, hv|
6
+ v.merge({"cluster[#{hv.first}]" => hv.last})
7
+ }
8
+
9
+ request(
10
+ :expects => 201,
11
+ :method => :post,
12
+ :path => "/#{account_id}/api/clusters",
13
+ :query => cluster_info
14
+ )
15
+ end
16
+
17
+ # GET /<accountID>/api/clusters/<clusterID>
18
+ def get_cluster_info(clusterID)
19
+ request(
20
+ :expects => 200,
21
+ :method => :get,
22
+ :path => "/#{account_id}/api/clusters/#{clusterID}"
23
+ )
24
+ end
25
+
26
+ # GET /<accountID>/api/clusters
27
+ def clusters(options={})
28
+ request(
29
+ :expects => 200,
30
+ :method => :get,
31
+ :path => "/#{account_id}/api/clusters",
32
+ :query => options
33
+ )
34
+ end
35
+
36
+ # DELETE /<accountID>/api/clusters/<clusterID>
37
+ def terminate_cluster(clusterID)
38
+ request(
39
+ :expects => 200,
40
+ :method => :delete,
41
+ :path => "/#{account_id}/api/clusters/#{clusterID}"
42
+ )
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ module Xplenty
2
+ class API
3
+ module Errors
4
+ class Error < StandardError; end
5
+
6
+ class ErrorWithResponse < Error
7
+ attr_reader :response
8
+
9
+ def initialize(message, response)
10
+ super message
11
+ @response = response
12
+ end
13
+ end
14
+
15
+ class RequestFailed < ErrorWithResponse; end
16
+ class NotModified < ErrorWithResponse; end
17
+ class BadRequest < ErrorWithResponse; end
18
+ class Unauthorized < ErrorWithResponse; end
19
+ class PaymentRequired < ErrorWithResponse; end
20
+ class Forbidden < ErrorWithResponse; end
21
+ class NotFound < ErrorWithResponse; end
22
+ class NotAcceptable < ErrorWithResponse; end
23
+ class UnsupportedMediaType < ErrorWithResponse; end
24
+ class UnprocessableEntity < ErrorWithResponse; end
25
+ class TooManyRequests < ErrorWithResponse; end
26
+ class InternalServerError < ErrorWithResponse; end
27
+ class BadGateway < ErrorWithResponse; end
28
+ class ServiceUnavailable < ErrorWithResponse; end
29
+
30
+ end
31
+ end
32
+ end