transcriptic 0.1.3 → 0.2.0

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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/bin/transcriptic +2 -4
  3. data/lib/thor/monkies.rb +3 -0
  4. data/lib/thor/monkies/shell.rb +3 -0
  5. data/lib/transcriptic.rb +86 -2
  6. data/lib/transcriptic/auth.rb +2 -63
  7. data/lib/transcriptic/base_generator.rb +25 -0
  8. data/lib/transcriptic/cli.rb +199 -8
  9. data/lib/transcriptic/client.rb +45 -38
  10. data/lib/transcriptic/commands/project.rb +37 -0
  11. data/lib/transcriptic/core_ext.rb +3 -0
  12. data/lib/transcriptic/core_ext/file.rb +7 -0
  13. data/lib/transcriptic/core_ext/file_utils.rb +15 -0
  14. data/lib/transcriptic/core_ext/pathname.rb +13 -0
  15. data/lib/transcriptic/core_ext/string.rb +8 -0
  16. data/lib/transcriptic/dependencies_generator.rb +13 -0
  17. data/lib/transcriptic/errors.rb +32 -0
  18. data/lib/transcriptic/labfile.rb +73 -0
  19. data/lib/transcriptic/project_generator.rb +56 -0
  20. data/lib/transcriptic/sbt.rb +58 -0
  21. data/lib/transcriptic/templates/LICENSE.erb +20 -0
  22. data/lib/transcriptic/templates/Labfile.erb +12 -0
  23. data/lib/transcriptic/templates/README.erb +3 -0
  24. data/lib/transcriptic/templates/app/Main.erb +11 -0
  25. data/lib/transcriptic/templates/project/Build.erb +59 -0
  26. data/lib/transcriptic/templates/project/Dependencies.erb +10 -0
  27. data/lib/transcriptic/templates/project/build.properties +1 -0
  28. data/lib/transcriptic/templates/project/plugins.sbt +5 -0
  29. data/lib/transcriptic/templates/sbt +1 -0
  30. data/lib/transcriptic/{helpers.rb → ui.rb} +124 -109
  31. data/lib/transcriptic/version.rb +2 -1
  32. data/lib/vendor/{transcriptic/okjson.rb → okjson.rb} +0 -0
  33. metadata +203 -46
  34. data/lib/transcriptic/command.rb +0 -233
  35. data/lib/transcriptic/command/base.rb +0 -157
  36. data/lib/transcriptic/command/console.rb +0 -10
  37. data/lib/transcriptic/command/data.rb +0 -29
  38. data/lib/transcriptic/command/help.rb +0 -124
  39. data/lib/transcriptic/command/login.rb +0 -35
  40. data/lib/transcriptic/command/run.rb +0 -108
@@ -1,11 +1,3 @@
1
- require 'rexml/document'
2
- require 'rest-client'
3
- require 'uri'
4
- require 'time'
5
- require 'transcriptic/auth'
6
- require 'transcriptic/helpers'
7
- require 'transcriptic/version'
8
-
9
1
  # A Ruby class to call the Transcriptic REST API. You might use this if you want to
10
2
  # manage your Transcriptic apps from within a Ruby program, such as Capistrano.
11
3
  #
@@ -16,9 +8,7 @@ require 'transcriptic/version'
16
8
  # transcriptic.create('myapp')
17
9
  #
18
10
  class Transcriptic::Client
19
-
20
- include Transcriptic::Helpers
21
- extend Transcriptic::Helpers
11
+ include Transcriptic::UI
22
12
 
23
13
  def self.version
24
14
  Transcriptic::VERSION
@@ -41,14 +31,12 @@ class Transcriptic::Client
41
31
  @host = host
42
32
  end
43
33
 
44
- # Get a list of stacks available to the app, with the current one marked.
45
- def list_stacks(app_name, options={})
46
- include_deprecated = options.delete(:include_deprecated) || false
34
+ def list_projects
35
+ json_decode get("/api/projects.json").to_s
36
+ end
47
37
 
48
- json_decode resource("/apps/#{app_name}/stack").get(
49
- :params => { :include_deprecated => include_deprecated },
50
- :accept => 'application/json'
51
- ).to_s
38
+ def project_info(name)
39
+ json_decode get("/api/projects/#{name}.json").to_s
52
40
  end
53
41
 
54
42
  class ProtocolException < RuntimeError; end
@@ -57,16 +45,24 @@ class Transcriptic::Client
57
45
  def list
58
46
  json_decode get('/api/runs.json').to_s
59
47
  end
60
-
48
+
49
+ def list_datasets(run_id = nil, project_id = nil)
50
+ json_decode get("/api/datasets.json?run_id=#{run_id}&project_id=#{project_id}").to_s
51
+ end
52
+
53
+ def get_dataset_info(dataset_id)
54
+ json_decode get("/api/datasets/#{dataset_id}").to_s
55
+ end
56
+
57
+ def delete_dataset(dataset_id)
58
+ json_decode delete("/api/datasets/#{dataset_id}").to_s
59
+ end
60
+
61
61
  # Show info such as mode, custom domain, and collaborators on an app.
62
62
  def info(name_or_domain)
63
63
  name_or_domain = name_or_domain.gsub(/^(http:\/\/)?(www\.)?/, '')
64
64
  end
65
65
 
66
- def organizations
67
- json_decode resource("/organizations").get(:accept => 'application/json').to_s
68
- end
69
-
70
66
  class Protocol
71
67
  attr_accessor :attached, :upid
72
68
 
@@ -80,9 +76,9 @@ class Transcriptic::Client
80
76
  def launch(command, attached=false)
81
77
  @attached = attached
82
78
  @response = @client.post(
83
- "/runs/#{@app}/services",
79
+ "/api/runs/#{@app}/confirm",
84
80
  command,
85
- :content_type => 'text/plain'
81
+ :content_type => 'application/json'
86
82
  )
87
83
  @next_chunk = @response.to_s
88
84
  @interval = 0
@@ -137,18 +133,29 @@ class Transcriptic::Client
137
133
  json_decode get("/api/runs/#{run_id}").to_s
138
134
  end
139
135
 
140
- def create_run(fd)
141
- json_decode post("/api/runs", File.open(fd).read, { 'Content-Type' => 'application/zip; charset=UTF-8' }).to_s
136
+ def create_run(fd, project_id)
137
+ payload = {
138
+ 'zipdata' => Base64.encode64(File.open(fd).read),
139
+ 'project_id' => project_id
140
+ }
141
+ json_decode post("/api/runs", payload, { 'Content-Type' => 'application/zip; charset=UTF-8' }).to_s
142
+ end
143
+
144
+ def launch_run(run_id)
145
+ json_decode post("/api/runs/#{run_id}/confirm").to_s
142
146
  end
143
147
 
144
- # Get a Protocol instance to execute commands against.
145
148
  def protocol(run_id, upid)
146
149
  Protocol.new(self, run_id, upid)
147
150
  end
148
151
 
149
152
  def read_logs(run_id, options=[])
150
153
  query = "&" + options.join("&") unless options.empty?
151
- url = get("/api/runs/#{run_id}/logs?#{query}").to_s
154
+ url = get("/api/runs/#{run_id}/logs.json?#{query}").to_s
155
+ if 'not_found' == url
156
+ error "Run #{run_id} not found!"
157
+ end
158
+
152
159
  uri = URI.parse(url);
153
160
  http = Net::HTTP.new(uri.host, uri.port)
154
161
 
@@ -180,9 +187,9 @@ class Transcriptic::Client
180
187
 
181
188
  ##################
182
189
 
183
- def resource(uri, options={})
190
+ def resource(uri, options={}, host=host)
184
191
  RestClient.proxy = ENV['HTTP_PROXY'] || ENV['http_proxy']
185
- resource = RestClient::Resource.new(realize_full_uri(uri), options)
192
+ resource = RestClient::Resource.new(realize_full_uri(uri, host), options)
186
193
  resource
187
194
  end
188
195
 
@@ -190,8 +197,8 @@ class Transcriptic::Client
190
197
  process(:get, uri, extra_headers)
191
198
  end
192
199
 
193
- def post(uri, payload="", extra_headers={}) # :nodoc:
194
- process(:post, uri, extra_headers, payload)
200
+ def post(uri, payload="", extra_headers={}, host=host) # :nodoc:
201
+ process(:post, uri, extra_headers, payload, host)
195
202
  end
196
203
 
197
204
  def put(uri, payload, extra_headers={}) # :nodoc:
@@ -202,19 +209,19 @@ class Transcriptic::Client
202
209
  process(:delete, uri, extra_headers)
203
210
  end
204
211
 
205
- def process(method, uri, extra_headers={}, payload=nil)
212
+ def process(method, uri, extra_headers={}, payload=nil, host=host)
206
213
  headers = transcriptic_headers.merge(extra_headers)
207
214
  args = [method, payload, headers].compact
208
215
 
209
216
  resource_options = default_resource_options_for_uri(uri)
210
217
 
211
218
  begin
212
- response = resource(uri, resource_options).send(*args)
219
+ response = resource(uri, resource_options, host).send(*args)
213
220
  rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, SocketError
214
- host = URI.parse(realize_full_uri(uri)).host
221
+ host = URI.parse(realize_full_uri(uri, host)).host
215
222
  error " ! Unable to connect to #{host}"
216
223
  rescue RestClient::SSLCertificateNotVerified => ex
217
- host = URI.parse(realize_full_uri(uri)).host
224
+ host = URI.parse(realize_full_uri(uri, host)).host
218
225
  error "WARNING: Unable to verify SSL certificate for #{host}\nTo disable SSL verification, run with TRANSCRIPTIC_SSL_VERIFY=disable"
219
226
  end
220
227
 
@@ -262,7 +269,7 @@ class Transcriptic::Client
262
269
 
263
270
  private
264
271
 
265
- def realize_full_uri(given)
272
+ def realize_full_uri(given, host=host)
266
273
  full_host = (host =~ /^http/) ? host : "https://www.#{host}"
267
274
  host = URI.parse(full_host)
268
275
  uri = URI.parse(given)
@@ -0,0 +1,37 @@
1
+ module Transcriptic
2
+ module CLI
3
+
4
+ # manage projects
5
+ #
6
+ class Project < Thor
7
+
8
+ desc "index", "upload FILENAME or DIRECTORY and launch it"
9
+ def index
10
+ if args.empty?
11
+ error("Usage: transcriptic project NAME")
12
+ end
13
+ name = args.shift
14
+ data = transcriptic.project_info(name)
15
+ display "Project \"#{data["name"]}\":"
16
+ display " shortname: #{data["codename"]}"
17
+ display " active runs: #{data["active_runs"].length}"
18
+ display " archived runs: #{data["completed_runs"].length}"
19
+ display " datasets created: #{data["datasets"].length}"
20
+ display " created at: #{data["created_at"]}"
21
+ end
22
+
23
+ # transcriptic project:list
24
+ desc "list", "list the projects the user can see"
25
+ def list
26
+ ret = transcriptic.list_projects
27
+ if ret.empty?
28
+ error("No projects for #{transcriptic.user}")
29
+ return
30
+ end
31
+ ret.each do |project|
32
+ display "\t" + project["codename"] + "\t\t" + project["name"]
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"].sort.each do |path|
2
+ require_relative "core_ext/#{File.basename(path, '.rb')}"
3
+ end
@@ -0,0 +1,7 @@
1
+ class File
2
+ class << self
3
+ def transcriptic_project?(path)
4
+ File.exists?(File.join(path, 'Labfile'))
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+
3
+ module FileUtils
4
+ class << self
5
+ # Override mv to avoid several bugs (Errno::EACCES in Windows, Errno::ENOENT
6
+ # with relative softlinks on Linux), by forcing to copy and delete instead
7
+ #
8
+ # @see {FileUtils::mv}
9
+ # @see {safe_mv}
10
+ def mv(src, dest, options = {})
11
+ FileUtils.cp_r(src, dest, options)
12
+ FileUtils.rm_rf(src)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class Pathname
2
+ def transcriptic_project?
3
+ self.join('Labfile').exist?
4
+ end
5
+
6
+ def transcriptic_project_root
7
+ self.ascend do |potential_root|
8
+ if potential_root.transcriptic_project?
9
+ return potential_root
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ class String
2
+ def prepend_each(separator, value)
3
+ lines(separator).collect { |x| value + x }.join
4
+ end
5
+ def shellescape
6
+ empty? ? "''" : gsub(/([^A-Za-z0-9_\-.,:\/@\n])/n, '\\\\\\1').gsub(/\n/, "'\n'")
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ require 'transcriptic/base_generator'
2
+
3
+ module Transcriptic
4
+ class DependenciesGenerator < BaseGenerator
5
+ include Transcriptic::UI
6
+
7
+ argument :dependencies
8
+
9
+ def generate
10
+ template 'project/Dependencies.erb', target.join('project/Dependencies.scala'), force: true
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ module Transcriptic
2
+ class TranscripticError < StandardError
3
+ class << self
4
+ def status_code(code)
5
+ define_method(:status_code) { code }
6
+ define_singleton_method(:status_code) { code }
7
+ end
8
+ end
9
+ alias_method :message, :to_s
10
+ end
11
+
12
+ class LabfileReadError < TranscripticError
13
+ def initialize(original_error)
14
+ @original_error = original_error
15
+ end
16
+
17
+ status_code(113)
18
+
19
+ def status_code
20
+ @original_error.respond_to?(:status_code) ? @original_error.status_code : 113
21
+ end
22
+
23
+ def to_s
24
+ [
25
+ "An error occurred while reading the Labfile:",
26
+ "",
27
+ " " + @original_error.to_s.split("\n").map(&:strip).join("\n "),
28
+ ].join("\n")
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,73 @@
1
+ #require 'transcriptic/downloader'
2
+
3
+ module Transcriptic
4
+ class Labfile
5
+ extend Forwardable
6
+
7
+ class << self
8
+ def from_file(file)
9
+ content = File.read(file)
10
+ object = new(file)
11
+ object.load(content)
12
+ rescue Errno::ENOENT => e
13
+ raise FileNotFound, "No Labfile found at: #{file}"
14
+ end
15
+ end
16
+
17
+ def initialize(path)
18
+ @filepath = path
19
+ @options = Hash.new
20
+ @dependencies = []
21
+ end
22
+
23
+ def load(content)
24
+ begin
25
+ instance_eval(content)
26
+ rescue => e
27
+ puts e
28
+ raise LabfileReadError.new(e)
29
+ end
30
+ self
31
+ end
32
+
33
+ def sha
34
+ @sha ||= Digest::SHA1.hexdigest File.read(filepath.to_s)
35
+ end
36
+
37
+ def options
38
+ @options
39
+ end
40
+
41
+ def name(name = nil)
42
+ @options[:name] = name
43
+ end
44
+
45
+ def author(name)
46
+ @options[:author] = name
47
+ end
48
+
49
+ def email(email)
50
+ @options[:email] = email
51
+ end
52
+
53
+ def version(arg)
54
+ @options[:version] = arg
55
+ end
56
+
57
+ def description(desc)
58
+ @options[:description] = desc
59
+ end
60
+
61
+ def dependency(group, name, version)
62
+ @dependencies << {
63
+ group: group,
64
+ name: name,
65
+ version: version
66
+ }
67
+ end
68
+
69
+ def dependencies
70
+ @dependencies
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,56 @@
1
+ require 'transcriptic/base_generator'
2
+
3
+ module Transcriptic
4
+ class ProjectGenerator < BaseGenerator
5
+
6
+ argument :name
7
+ class_option :package,
8
+ type: :string,
9
+ default: "org.autoprotocol.unclaimed"
10
+ class_option :author,
11
+ type: :string,
12
+ default: "John Appleseed"
13
+ class_option :email,
14
+ type: :string,
15
+ default: "author@example.edu"
16
+ class_option :description,
17
+ type: :string,
18
+ default: false
19
+
20
+ def generate
21
+ empty_directory target.join('app')
22
+ empty_directory target.join('project')
23
+ empty_directory target.join('lib')
24
+
25
+ template 'app/Main.erb', target.join('app/Main.scala')
26
+ template 'project/Build.erb', target.join('project/Build.scala')
27
+ copy_file 'project/build.properties', target.join('project/build.properties')
28
+ copy_file 'project/plugins.sbt', target.join('project/plugins.sbt')
29
+ template 'LICENSE.erb', target.join('LICENSE')
30
+ template 'Labfile.erb', target.join('Labfile')
31
+ template 'README.erb', target.join('README.md')
32
+
33
+ Transcriptic::DependenciesGenerator.new([File.join(Dir.pwd, name), []], options).invoke_all
34
+ end
35
+
36
+ def description
37
+ options[:description]
38
+ end
39
+
40
+ def package
41
+ options[:package]
42
+ end
43
+
44
+ def author
45
+ options[:author]
46
+ end
47
+
48
+ def email
49
+ options[:email]
50
+ end
51
+
52
+ def copyright_year
53
+ Time.now.year
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,58 @@
1
+ module Transcriptic
2
+ class SBT
3
+ class << self
4
+ include Transcriptic::UI
5
+
6
+ def compile
7
+ ensure_installed
8
+ sbt("package")
9
+ end
10
+
11
+ def stage
12
+ ensure_installed
13
+ sbt("stage")
14
+ end
15
+
16
+ private
17
+ def ensure_installed
18
+ stat = `which sbt`
19
+ if stat.empty?
20
+ output_with_arrow "Downloading sbt..."
21
+ Transcriptic::SBT::Installer.new(["/usr/local"], {}).invoke_all
22
+ end
23
+ end
24
+
25
+ def sbt(action)
26
+ base = Transcriptic.find_labfile.dirname
27
+ output_with_arrow "Detected Scala sources in app..."
28
+ output_with_arrow "Compiling..."
29
+ display
30
+
31
+ code = IO.popen("sbt #{action}") do |stream|
32
+ stream.each do |line|
33
+ output_with_indent line
34
+ end
35
+ end
36
+
37
+ display
38
+
39
+ if 0 == $?
40
+ output_with_arrow "Compilation succeeded."
41
+ true
42
+ else
43
+ output_with_arrow "Errors occurred!"
44
+ false
45
+ end
46
+ end
47
+ end
48
+
49
+ class Installer < BaseGenerator
50
+ def install
51
+ get "http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.12.3/sbt-launch.jar",
52
+ target.join("sbt/sbt-launch.jar")
53
+ copy_file 'sbt', target.join('bin/sbt')
54
+ chmod target.join('bin/sbt'), 0755
55
+ end
56
+ end
57
+ end
58
+ end