zillabyte-cli 0.0.9

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.
Files changed (53) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +20 -0
  4. data/README.md +29 -0
  5. data/bin/zillabyte +18 -0
  6. data/lib/zillabyte/api/base.rb +11 -0
  7. data/lib/zillabyte/api/data.rb +126 -0
  8. data/lib/zillabyte/api/flows.rb +239 -0
  9. data/lib/zillabyte/api/locks.rb +4 -0
  10. data/lib/zillabyte/api/logs.rb +32 -0
  11. data/lib/zillabyte/api/metrics.rb +48 -0
  12. data/lib/zillabyte/api/queries.rb +58 -0
  13. data/lib/zillabyte/api/semantic_tags.rb +24 -0
  14. data/lib/zillabyte/api/settings.rb +8 -0
  15. data/lib/zillabyte/api/sources.rb +28 -0
  16. data/lib/zillabyte/api/zillalogs.rb +66 -0
  17. data/lib/zillabyte/api.rb +170 -0
  18. data/lib/zillabyte/auth.rb +155 -0
  19. data/lib/zillabyte/cli/auth.rb +33 -0
  20. data/lib/zillabyte/cli/base.rb +161 -0
  21. data/lib/zillabyte/cli/config.rb +63 -0
  22. data/lib/zillabyte/cli/counters.rb +61 -0
  23. data/lib/zillabyte/cli/flows.rb +702 -0
  24. data/lib/zillabyte/cli/help.rb +137 -0
  25. data/lib/zillabyte/cli/helpers/data_schema_builder.rb +3 -0
  26. data/lib/zillabyte/cli/host.rb +21 -0
  27. data/lib/zillabyte/cli/logs.rb +118 -0
  28. data/lib/zillabyte/cli/query.rb +172 -0
  29. data/lib/zillabyte/cli/relations.rb +326 -0
  30. data/lib/zillabyte/cli/sources.rb +37 -0
  31. data/lib/zillabyte/cli/templates/js/simple_function.js +33 -0
  32. data/lib/zillabyte/cli/templates/js/zillabyte.conf.yaml +2 -0
  33. data/lib/zillabyte/cli/templates/python/requirements.txt +7 -0
  34. data/lib/zillabyte/cli/templates/python/simple_function.py +27 -0
  35. data/lib/zillabyte/cli/templates/python/zillabyte.conf.yaml +4 -0
  36. data/lib/zillabyte/cli/templates/ruby/Gemfile +3 -0
  37. data/lib/zillabyte/cli/templates/ruby/simple_function.rb +36 -0
  38. data/lib/zillabyte/cli/templates/ruby/zillabyte.conf.yaml +2 -0
  39. data/lib/zillabyte/cli/version.rb +11 -0
  40. data/lib/zillabyte/cli/zillalogs.rb +86 -0
  41. data/lib/zillabyte/cli.rb +37 -0
  42. data/lib/zillabyte/command.rb +254 -0
  43. data/lib/zillabyte/common/progress.rb +17 -0
  44. data/lib/zillabyte/common/tar.rb +102 -0
  45. data/lib/zillabyte/common.rb +13 -0
  46. data/lib/zillabyte/helpers.rb +49 -0
  47. data/lib/zillabyte/queries.rb +39 -0
  48. data/lib/zillabyte-cli/version.rb +5 -0
  49. data/lib/zillabyte-cli.rb +5 -0
  50. data/zillabyte-cli.gemspec +42 -0
  51. data/zillabyte_emails.csv +1 -0
  52. data/zillaconf.json +3 -0
  53. metadata +278 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTVkNDVmMWE1NWJiMzhmMTk5M2IxOGJkZDExYjIxMTY3MGRiNDBjMg==
5
+ data.tar.gz: !binary |-
6
+ ZGEyMjU3NjM5MTE0NWE1N2I4ZDdkZjZlNTk2NmQzNzYzYmI2ZGZkYw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NDk2ZTcyMjk1ODg5NTE3NTU0ZGFmNDlkYTY4MWIzOGEyYjEyYjJlNDk0YTI2
10
+ OTAwYmRkMWU1MzliOWYyMmIyZWFjMTFiZWI0NWE0NmUzZTA3Y2Y4ZTkyNjMz
11
+ ODBkYWQ1ZDA1MjkzZGE1NTg5MDA0NzMwZmFhYzNhNmRlYzBiNTY=
12
+ data.tar.gz: !binary |-
13
+ MjI3YzIzNGMzMjkzY2JjNjZmMjc2YzU4MDU3Y2RlNTQzYjE0OTYzN2VhNTc4
14
+ ZWRmMGZhMjc2M2FiYjkwYTc1OGY2YzUwNjM3YmRiOTU1NzA2OWFiNzBiNWU4
15
+ YTRjYTNiMzQyYWM5ZmVhZjdlZDY1MjI5ZDJkNjUzZjc3OWU1NTE=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in zillabyte-cli.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Zillabyte
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ 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, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Zillabyte
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'zillabyte'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install zillabyte
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/bin/zillabyte ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'zillabyte' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ require_relative '../lib/zillabyte-cli'
17
+ Zillabyte::CLI.start(*ARGV)
18
+
@@ -0,0 +1,11 @@
1
+ class Zillabyte::API::Base
2
+
3
+ def initialize(api)
4
+ @api = api
5
+ end
6
+
7
+ def request(*args)
8
+ @api.request(*args)
9
+ end
10
+
11
+ end
@@ -0,0 +1,126 @@
1
+ require 'net/http'
2
+
3
+ class Zillabyte::API::Data < Zillabyte::API::Base
4
+
5
+
6
+ # # GET /datasets
7
+ # def list(options = {})
8
+ #
9
+ # options = {
10
+ # # TODO
11
+ # }.merge(options)
12
+ #
13
+ # res = @api.request(
14
+ # :expects => 200,
15
+ # :method => :get,
16
+ # :path => "/datasets"
17
+ # )
18
+ #
19
+ # res.body
20
+ #
21
+ # end
22
+
23
+
24
+
25
+
26
+ # GET /datasets/1
27
+ def get(id, options = {})
28
+
29
+ options = {
30
+ :name => id
31
+ # rows
32
+ # schema
33
+ # relations
34
+ }.merge(options)
35
+
36
+ res = @api.request(
37
+ :expects => 200,
38
+ :method => :get,
39
+ :path => "/relations/#{id}",
40
+ :body => options.to_json
41
+ )
42
+
43
+ res.body
44
+
45
+ end
46
+
47
+
48
+ # POST /datasets
49
+ def create(name, options = {})
50
+
51
+ options = {
52
+ :name => name,
53
+ # rows
54
+ # schema
55
+ # relations
56
+ }.merge(options)
57
+
58
+ res = @api.request(
59
+ :expects => 200,
60
+ :method => :post,
61
+ :path => "/relations",
62
+ :body => options.to_json
63
+ )
64
+
65
+ res.body
66
+
67
+ end
68
+
69
+
70
+
71
+
72
+
73
+
74
+ # POST /datasets/1/append
75
+ def append(id, options = {})
76
+ opts = {:name => id}
77
+ file = options[:file] if options[:file]
78
+ if(file)
79
+ opts[:size] = File.size(file)
80
+ options.delete(:file)
81
+ end
82
+ options = opts.merge(options)
83
+
84
+ res = @api.request(
85
+ :expects => 200,
86
+ :method => :post,
87
+ :path => "/relations/#{id}/append",
88
+ :body => options.to_json
89
+ )
90
+
91
+ hash = res.body
92
+ if(hash['uri'])
93
+ uri = URI(hash['uri'])
94
+ response = nil
95
+ try_again = 1
96
+ while(try_again)
97
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
98
+ request = Net::HTTP::Put.new(uri.request_uri)
99
+ request.body_stream = Zillabyte::Common::Tar.tar(file, [])
100
+ request['Content-Length'] = request.body_stream.size
101
+ request['Content-Type'] = ''
102
+ response = http.request(request)
103
+ if response.code.to_i >= 300
104
+ try_again = 1
105
+ break
106
+ end
107
+ try_again = nil
108
+ end
109
+ end
110
+ hash[:appended] = opts[:size]
111
+ hash.delete('uri')
112
+ res = @api.request(
113
+ :expects => 200,
114
+ :method => :post,
115
+ :path => "/relations/#{id}/store",
116
+ :body => options.to_json
117
+ )
118
+ end
119
+ hash
120
+
121
+ end
122
+
123
+
124
+
125
+
126
+ end
@@ -0,0 +1,239 @@
1
+ require 'net/http'
2
+ require 'mkfifo'
3
+ require 'zillabyte/cli/config'
4
+
5
+ class Zillabyte::API::Flows < Zillabyte::API::Base
6
+
7
+
8
+ # GET /flows
9
+ def list(options = {})
10
+
11
+ options = {
12
+ # TODO
13
+ }.merge(options)
14
+
15
+ res = @api.request(
16
+ :expects => 200,
17
+ :method => :get,
18
+ :path => "/flows"
19
+ )
20
+
21
+ res.body
22
+
23
+ end
24
+
25
+
26
+
27
+
28
+ # GET /flows/id
29
+ def get(id, options = {})
30
+
31
+ options = {
32
+ # TODO
33
+ }.merge(options)
34
+
35
+ res = @api.request(
36
+ :expects => 200,
37
+ :method => :get,
38
+ :path => "/flows/#{id}",
39
+ :body => options.to_json
40
+ )
41
+
42
+ res.body
43
+
44
+ end
45
+
46
+
47
+
48
+
49
+ # GET /flows/id/kill
50
+ def kill(id, options = {})
51
+
52
+ options = {
53
+ # TODO
54
+ }.merge(options)
55
+
56
+ res = @api.request(
57
+ :expects => 200,
58
+ :method => :post,
59
+ :path => "/flows/#{id}/kill",
60
+ :body => options.to_json
61
+ )
62
+
63
+ res.body
64
+
65
+ end
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+ # GET /flows/id
75
+ def pull_to_directory(id, dir, progress = nil, options = {})
76
+
77
+ # Get the resource. note query params
78
+ progress.display "downloading ##{id}" if progress
79
+ res = @api.request(
80
+ :expects => 200,
81
+ :method => :get,
82
+ :path => "/flows/#{id}/download"
83
+ #:path => "/flows/#{id}?indirect_url=1"
84
+ #:path => "/flows/#{id}?tar=1"
85
+ )
86
+
87
+ hash = res.body
88
+ unless hash['status'] == 'error'
89
+ if(hash['tar'])
90
+ progress.display "unpacking to #{dir}" if progress
91
+ tar = StringIO.new(Base64.decode64(hash['tar']))
92
+ hash.delete('tar')
93
+ Zillabyte::Common::Tar.untar(tar, dir)
94
+ #If you get an uri instead of the tar, then download the file directly from s3
95
+ elsif(hash['uri'])
96
+ progress.display "downloading ##{id} to #{dir}" if progress
97
+ uri = URI(hash['uri'])
98
+ try_again = 1
99
+ while(try_again)
100
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
101
+ request = Net::HTTP::Get.new(uri.request_uri)
102
+ response = http.request(request)
103
+ if response.code.to_i >= 300
104
+ try_again = 1
105
+ break
106
+ end
107
+ tar = StringIO.new(response.body)
108
+ Zillabyte::Common::Tar.untar(tar, dir)
109
+ try_again = nil
110
+ end
111
+ end
112
+ hash.delete('uri')
113
+ end
114
+ end
115
+
116
+ hash
117
+
118
+ end
119
+
120
+
121
+
122
+ # POST /flows
123
+ def push_directory(dir, progress = nil, options = {})
124
+
125
+ # Get the meta info
126
+ options[:local_flag] = 1
127
+ hash = Zillabyte::API::Flows.get_rich_meta_info_from_script(dir, progress, options)
128
+ if hash.nil?
129
+ error "unable to extract flow meta information"
130
+ end
131
+
132
+ # Tar up everything...
133
+ hash['ignore_files'] ||= []
134
+ hash['ignore_files'] << "info_to_ruby.in"
135
+ hash['ignore_files'] << "vEnv"
136
+
137
+ top_dir = hash['top_dir'] || "."
138
+ ignore_files = hash['ignore_files'] || []
139
+ progress.display("packaging directory... ", false) if progress
140
+ tar = Zillabyte::Common::Tar.tar(top_dir, ignore_files)
141
+ progress.display("done") if progress
142
+
143
+ hash.delete('pwd')
144
+
145
+ options = {
146
+ :name => hash['name'],
147
+ :meta => hash,
148
+ # :tar => Base64.encode64(tar.read)
149
+ }.merge(options)
150
+
151
+ progress.display("uploading #{tar.size} bytes... ", false) if progress
152
+ res = @api.request(
153
+ :expects => 200,
154
+ :method => :post,
155
+ :path => "/flows",
156
+ :body => options.to_json
157
+ )
158
+
159
+ if(res.body['uri'])
160
+ uri = URI(res.body['uri'])
161
+ try_again = 1
162
+ while(try_again)
163
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
164
+ request = Net::HTTP::Put.new(uri.request_uri)
165
+ request.body_stream = tar
166
+ request['Content-Length'] = request.body_stream.size
167
+ request['Content-Type'] = ''
168
+ response = http.request(request)
169
+ if response.code.to_i >= 300
170
+ try_again = 1
171
+ break
172
+ end
173
+ try_again = nil
174
+ end
175
+ end
176
+ res.body.delete('uri')
177
+ end
178
+ progress.display("done")
179
+ res.body
180
+
181
+ end
182
+
183
+ ####################################################IMPORTANT####################################################
184
+ # #
185
+ # get_rich_meta_info_from_script only works with zillabyte flows:push now! The pipe "info_to_ruby.in" is #
186
+ # hardcoded as the meta info passing pipe, so if 2 processes are trying to access it simultaneously there might #
187
+ # be problems since it gets created/destroyed within this script (attempting to create a fifo that already #
188
+ # exists or deleting a fifo that still has information in it may occur). #
189
+ # #
190
+ ####################################################IMPORTANT####################################################
191
+ def self.get_rich_meta_info_from_script(dir, progress = nil, options = {})
192
+ hash = Zillabyte::CLI::Config.get_config_info(dir, progress, options)
193
+ if hash.nil?
194
+ return {"status" => "error", "error" => "invalid_directory", "error_message" => "The specified directory (#{dir}) does not appear to contain a valid Zillabyte configuration file."}
195
+ end
196
+
197
+ full_script = File.join(dir, hash['script'])
198
+ command = nil
199
+
200
+ info_file = SecureRandom.uuid
201
+ arg = "--info --file #{info_file}"
202
+ stderr = ""
203
+ stderr = " 2> /dev/null" unless options[:test]
204
+
205
+ case hash["language"]
206
+ when "ruby"
207
+ command = "cd \"#{dir}\"; unset BUNDLE_GEMFILE; ZILLABYTE_HARNESS=1 bundle exec ruby \"#{full_script}\" #{arg} #{stderr}"
208
+ command = "cd \"#{dir}\"; unset BUNDLE_GEMFILE; ZILLABYTE_HARNESS=1 bundle exec ruby \"#{full_script}\" #{arg} #{stderr}"
209
+ when "python"
210
+ if(File.directory?("#{dir}/vEnv"))
211
+ command = "cd \"#{dir}\"; PYTHONPATH=~/zb1/multilang/python/Zillabyte #{dir}/vEnv/bin/python \"#{full_script}\" #{arg} #{stderr}"
212
+ else
213
+ command = "cd \"#{dir}\"; PYTHONPATH=~/zb1/multilang/python/Zillabyte python \"#{full_script}\" #{arg} 2> /dev/null"
214
+ end
215
+ when "js"
216
+ # command = "#{Zillabyte::API::CASPERJS_BIN} #{Zillabyte::API::API_CLIENT_JS} \"#{full_script}\" --info"
217
+ command = "cd \"#{dir}\"; NODE_PATH=~/zb1/multilang/js #{Zillabyte::API::NODEJS_BIN} \"#{full_script}\" #{arg} #{stderr}"
218
+ else
219
+ progress.error "unsupported language: #{hash["language"]}" if progress
220
+ return nil
221
+ end
222
+
223
+ results = Zillabyte::Command::Flows.get_info(command, info_file, options)
224
+
225
+ begin
226
+ meta = JSON.parse(results.split("\n").first.strip) # Throws error if invalid json
227
+ rescue Exception => e
228
+ progress.error "the underlying flow did not return a valid result. command: #{command} error: #{e.message}" if progress
229
+ exit
230
+ end
231
+
232
+
233
+ # Merge with the new info
234
+ return hash.merge(meta)
235
+
236
+ end
237
+
238
+
239
+ end
@@ -0,0 +1,4 @@
1
+ module Zillabyte
2
+ module Lock
3
+ end
4
+ end
@@ -0,0 +1,32 @@
1
+ require 'net/http'
2
+ require 'open-uri'
3
+
4
+ class Zillabyte::API::Logs < Zillabyte::API::Base
5
+
6
+
7
+ # GET /flows/ID/logs
8
+ def get(flow_id, operation_id, options = {})
9
+
10
+ options = {
11
+ }.merge(options)
12
+
13
+ since = ""
14
+ if options[:since]
15
+ since = "?since=#{URI::encode(options[:since])}"
16
+ end
17
+
18
+ res = @api.request(
19
+ :expects => 200,
20
+ :method => :get,
21
+ :path => "/flows/#{flow_id}/logs/#{operation_id}#{since}"
22
+ )
23
+
24
+ res.body
25
+
26
+ end
27
+
28
+
29
+
30
+
31
+
32
+ end
@@ -0,0 +1,48 @@
1
+ class Zillabyte::API::Metrics < Zillabyte::API::Base
2
+
3
+
4
+ # GET /metrics
5
+ def list(options = {})
6
+
7
+ options = {
8
+ # TODO
9
+ }.merge(options)
10
+
11
+ res = @api.request(
12
+ :expects => 200,
13
+ :method => :get,
14
+ :path => "/metrics"
15
+ )
16
+
17
+ res.body
18
+
19
+ end
20
+
21
+
22
+
23
+ # GET /metrics
24
+ def show(id, options = {}, block = nil)
25
+
26
+
27
+ if block
28
+ res = @api.request(
29
+ :expects => 200,
30
+ :method => :get,
31
+ :path => "/metrics/#{id}?#{options.to_query}",
32
+ :response_block => block
33
+ )
34
+ else
35
+ res = @api.request(
36
+ :expects => 200,
37
+ :method => :get,
38
+ :path => "/metrics/#{id}?#{options.to_query}",
39
+ )
40
+
41
+ end
42
+
43
+ res.body
44
+
45
+ end
46
+
47
+
48
+ end
@@ -0,0 +1,58 @@
1
+ class Zillabyte::API::Queries < Zillabyte::API::Base
2
+
3
+
4
+ # GET /sxp
5
+ def sxp(expression, options = {})
6
+
7
+ options = {
8
+ 'sxp' => expression
9
+ }.merge(options)
10
+
11
+ res = request(
12
+ :expects => 200,
13
+ :method => :post,
14
+ :path => "/query_sxp",
15
+ :body => options.to_json
16
+ )
17
+
18
+ res.body
19
+
20
+ end
21
+
22
+
23
+
24
+ # GET /sql
25
+ def sql(expression, options = {})
26
+
27
+ options = {
28
+ 'sql' => expression
29
+ }.merge(options)
30
+
31
+ res = request(
32
+ :expects => 200,
33
+ :method => :post,
34
+ :path => "/query_sql",
35
+ :body => options.to_json
36
+ )
37
+
38
+ res.body
39
+
40
+ end
41
+
42
+
43
+
44
+ def agnostic(expression, options = {})
45
+ case expression
46
+ when Array
47
+ return sxp(expression, options)
48
+ when String
49
+ return sql(expression, options)
50
+ else
51
+ throw "unknown expression type: #{expression}"
52
+ end
53
+ end
54
+
55
+
56
+
57
+
58
+ end
@@ -0,0 +1,24 @@
1
+
2
+ class Zillabyte::API::SemanticTags < Zillabyte::API::Base
3
+
4
+
5
+ # GET /semantic_tags
6
+ def list(options = {})
7
+
8
+ options = {
9
+ # TODO
10
+ }.merge(options)
11
+
12
+ res = @api.request(
13
+ :expects => 200,
14
+ :method => :get,
15
+ :path => "/semantic_tags"
16
+ )
17
+
18
+ res.body
19
+
20
+ end
21
+
22
+
23
+
24
+ end
@@ -0,0 +1,8 @@
1
+ module Zillabyte
2
+ class API
3
+ # PY_VIRTUAL_ENV_DIR = "/tmp/vEnv"
4
+ CASPERJS_BIN = "/usr/local/bin/casperjs"
5
+ API_CLIENT_JS = File.join(ENV['HOME'], "zb1/api.client.js/api.coffee")
6
+ NODEJS_BIN = "/usr/local/bin/node"
7
+ end
8
+ end
@@ -0,0 +1,28 @@
1
+ class Zillabyte::API::Sources < Zillabyte::API::Base
2
+
3
+
4
+ # GET /sources
5
+ def list(options = {})
6
+
7
+ options = {
8
+ # TODO
9
+ }.merge(options)
10
+
11
+ res = @api.request(
12
+ :expects => 200,
13
+ :method => :get,
14
+ :path => "/sources"
15
+ )
16
+
17
+ res.body
18
+
19
+ end
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+ end