whaler 0.0.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b74215d004f872034912eb21602eba9ce3883bd0
4
- data.tar.gz: 0f6a846cf2534a7d2070d61395eb7eb212eff398
3
+ metadata.gz: dbfca957958dc9ca8c9c9ba89cfa730be5cf4163
4
+ data.tar.gz: 8ed7262a6ce61c131c0564e9edb66a231e7e2041
5
5
  SHA512:
6
- metadata.gz: a21da673f0bf88bde9ded076416816c90c8441adbf7dce7df3b688b4256c0db8655c7f8153e43d271323a99e96cb3f261eb2c366f95768675f0ffa75f7381fb2
7
- data.tar.gz: 9536c642e37a45e72403a8e7dcb30110c657076be402c93676199cab8c3b7e4b47842b6939546a39aaba5a1ab9c198581d1ec38f7396616dc885d2bd8dfba164
6
+ metadata.gz: 1359ea363869da55fede9c7a4dcb97cfce74823bc2db54b1b57b2fcbd3ab9d9d22ba87d5f071381b892e3ac85a435b9e4232643b6562e6da0c3e928a6855d1d0
7
+ data.tar.gz: 6564f31f655793ec01504697489e3bf8c176fe455cc7b12663f4e2c146a3bcd7949f89e76c03d9563b9a5bd6c8171fb63dae55df58b26397146b31da937c0036
data/bin/whaler ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "whaler"
4
+
5
+ begin
6
+ Whaler::CLI.new(ARGV).run
7
+ rescue => e
8
+ $stderr.puts "whaler: Error: #{e.message}"
9
+ exit 1
10
+ end
@@ -0,0 +1,8 @@
1
+ class Whaler::API
2
+ def self.login(username, password)
3
+ post("/login", body: {
4
+ username: username,
5
+ password: password
6
+ })
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ class Whaler::API
2
+ def self.run(app, command)
3
+ post("/run", body: {
4
+ app: app,
5
+ command: command
6
+ })
7
+ rescue Errors::NotFound => e
8
+ raise e.exception("No such app: #{app}")
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ class Whaler::API
2
+ module Errors
3
+ class Error < StandardError
4
+ attr_reader :response
5
+
6
+ def initialize(message, response)
7
+ super "#{message} (#{response.code})"
8
+ @response = response
9
+ end
10
+ end
11
+
12
+ class NotFound < Error; end
13
+ class Unauthorized < Error; end
14
+ end
15
+ end
data/lib/whaler/api.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'httparty'
2
+ require 'whaler/api/errors'
3
+
4
+ Dir[File.join(File.dirname(__FILE__), "api", "actions", "*.rb")].each do |file|
5
+ require file
6
+ end
7
+
8
+ class Whaler::API
9
+ include HTTParty
10
+
11
+ DEFAULT_BASE_URI = "http://api.scalewhale.io"
12
+
13
+ base_uri ENV['WHALER_BASE_URI'] || DEFAULT_BASE_URI
14
+ headers "Accept" => "application/vnd.sw+json; version=1"
15
+
16
+ class << self
17
+ def setup(api_key)
18
+ basic_auth '', api_key
19
+ self
20
+ end
21
+
22
+ private
23
+
24
+ def perform_request(http_method, path, options, &block)
25
+ response = super
26
+ response.success? ? response : error_for(response)
27
+ end
28
+
29
+ def error_for(response)
30
+ klass = case response.code
31
+ when 401 then Errors::Unauthorized
32
+ when 404 then Errors::NotFound
33
+ else Errors::Error
34
+ end
35
+ raise klass.new(response.message, response)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ require 'highline/import'
2
+
3
+ module Whaler
4
+ class Auth
5
+ class << self
6
+
7
+ def api
8
+ @api ||= (
9
+ API.setup(credentials.last)
10
+ API
11
+ )
12
+ end
13
+
14
+ def credentials
15
+ CredentialsStore.read || ask_and_save_credentials
16
+ end
17
+
18
+ def delete_credentials
19
+ CredentialsStore.delete
20
+ @api = nil
21
+ end
22
+
23
+ def ask_and_save_credentials(username = nil, password = nil)
24
+ username ||= ask_username
25
+ password ||= ask_password
26
+ api_key = get_api_key(username, password)
27
+ CredentialsStore.write(username, api_key)
28
+ # check_for_associated_ssh_key unless Heroku::Command.current_command == "keys:add"
29
+ [username, api_key]
30
+ rescue Whaler::API::Errors::Unauthorized => e
31
+ delete_credentials
32
+ $stderr.puts "Authentication failed, please try again"
33
+ exit 1
34
+ rescue Exception => e
35
+ delete_credentials
36
+ raise e
37
+ end
38
+
39
+ private
40
+
41
+ def get_api_key(username, password)
42
+ API.login(username, password).body.strip
43
+ end
44
+
45
+ def ask_username
46
+ ask("Email: ")
47
+ end
48
+
49
+ def ask_password
50
+ ask("Password: ") { |q| q.echo = "•" }
51
+ end
52
+
53
+ end
54
+ end
55
+ end
data/lib/whaler/cli.rb ADDED
@@ -0,0 +1,61 @@
1
+ require 'slop'
2
+ require 'git'
3
+
4
+ module Whaler
5
+ class CLI
6
+ EX_USAGE = 64
7
+ EX_DATAERR = 65
8
+ EX_NOINPUT = 66
9
+
10
+ GIT_URI = "git@scalewhale.io"
11
+
12
+ def self.app_opts(command)
13
+ command.on "a=", "app=", "Application"
14
+ end
15
+
16
+ def self.app(opts)
17
+ opts[:app] || detect_app
18
+ end
19
+
20
+ def self.detect_app
21
+ apps = Git.open(".").remotes.map do |remote|
22
+ if m = remote.url.match(/#{GIT_URI}:(.+)\.git/)
23
+ m[1]
24
+ end
25
+ end.uniq
26
+
27
+ if apps.size == 0
28
+ $stderr.puts "No app found. Please run whaler from the app folder or use the --app option"
29
+ exit EX_NOINPUT
30
+ elsif apps.size > 1
31
+ $stderr.puts "Multiple apps found (#{apps.join(", ")}). Please specify one with the --app option"
32
+ exit EX_DATAERR
33
+ end
34
+
35
+ apps.first
36
+ end
37
+
38
+ def initialize(args)
39
+ @args = args
40
+ end
41
+
42
+ def run
43
+ Slop.parse(args, help: true, strict: true) do
44
+ context = self
45
+ Command.commands.each do |block|
46
+ self.instance_eval(&block)
47
+ end
48
+
49
+ run do |opts, args|
50
+ $stderr.puts opts.help
51
+ exit EX_USAGE
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader :args
59
+
60
+ end
61
+ end
@@ -0,0 +1,22 @@
1
+ module Whaler
2
+ Command.register do
3
+
4
+ command "login" do
5
+ on "u=", "username=", "Username (your e-mail)"
6
+ on "p=", "password=", "Password"
7
+
8
+ run do |opts, args|
9
+ Auth.ask_and_save_credentials(opts[:username], opts[:password])
10
+ puts "Authentication successful"
11
+ end
12
+ end
13
+
14
+ command "logout" do
15
+ run do |opts, args|
16
+ Auth.delete_credentials
17
+ puts "Logged out"
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module Whaler
2
+ Command.register do
3
+
4
+ command "run", strict: false do
5
+ CLI.app_opts(self)
6
+
7
+ banner "Usage: whaler run [options] <command>"
8
+
9
+ run do |opts, args|
10
+ command = args.join(" ")
11
+ if command.empty?
12
+ $stderr.puts opts.help
13
+ exit CLI::EX_USAGE
14
+ end
15
+
16
+ puts Auth.api.run(CLI.app(opts), command).body
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module Whaler::Command
2
+
3
+ module ClassMethods
4
+ def load
5
+ Dir[File.join(File.dirname(__FILE__), "command", "*.rb")].each do |file|
6
+ require file
7
+ end
8
+ end
9
+
10
+ def commands
11
+ @@comands ||= []
12
+ end
13
+
14
+ def register(&block)
15
+ commands.push(block)
16
+ end
17
+ end
18
+ extend ClassMethods
19
+
20
+ end
@@ -0,0 +1,51 @@
1
+ require 'netrc'
2
+
3
+ class Whaler::CredentialsStore
4
+ HOST = "api.scalewhale.io"
5
+
6
+ class << self
7
+
8
+ def read
9
+ return unless netrc
10
+ @credentials ||= netrc[HOST]
11
+ end
12
+
13
+ def write(username, api_key)
14
+ @credentials = [username, api_key]
15
+ FileUtils.mkdir_p(File.dirname(netrc_path))
16
+ FileUtils.touch(netrc_path)
17
+ FileUtils.chmod(0600, netrc_path) unless RUBY_PLATFORM =~ /mswin32|mingw32/
18
+ netrc[HOST] = @credentials
19
+ netrc.save
20
+ end
21
+
22
+ def delete
23
+ @credentials = nil
24
+ return unless netrc
25
+ netrc.delete(HOST)
26
+ netrc.save
27
+ end
28
+
29
+ private
30
+
31
+ def netrc_path
32
+ default = Netrc.default_path
33
+ encrypted = default + ".gpg"
34
+ File.exists?(encrypted) ? encrypted : default
35
+ end
36
+
37
+ def netrc
38
+ @netrc ||= begin
39
+ File.exists?(netrc_path) && Netrc.read(netrc_path)
40
+ rescue => error
41
+ if error.message =~ /^Permission bits for/
42
+ perm = File.stat(netrc_path).mode & 0777
43
+ abort("Permissions #{perm} for '#{netrc_path}' are too open. You should run `chmod 0600 #{netrc_path}` so that your credentials are NOT accessible by others.")
44
+ else
45
+ raise error
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+ end
data/lib/whaler.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Whaler
2
+ require 'whaler/credentials_store'
3
+ require 'whaler/api'
4
+ require 'whaler/auth'
5
+ require 'whaler/command'
6
+ require 'whaler/cli'
7
+
8
+ Command.load
9
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whaler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ScaleWhale
@@ -39,26 +39,81 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.6.7
41
41
  - !ruby/object:Gem::Dependency
42
- name: cocaine
42
+ name: slop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '='
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.5.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.5.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: highline
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: 0.5.4
61
+ version: 1.6.21
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - '='
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.6.21
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.13'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: git
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.2.6
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
53
95
  - !ruby/object:Gem::Version
54
- version: 0.5.4
96
+ version: 1.2.6
55
97
  description: ScaleWhale CLI
56
98
  email: support@scalewhale.eu
57
- executables: []
99
+ executables:
100
+ - whaler
58
101
  extensions: []
59
102
  extra_rdoc_files: []
60
103
  files:
61
104
  - README.md
105
+ - bin/whaler
106
+ - lib/whaler.rb
107
+ - lib/whaler/api.rb
108
+ - lib/whaler/api/actions/login.rb
109
+ - lib/whaler/api/actions/run.rb
110
+ - lib/whaler/api/errors.rb
111
+ - lib/whaler/auth.rb
112
+ - lib/whaler/cli.rb
113
+ - lib/whaler/command.rb
114
+ - lib/whaler/command/login.rb
115
+ - lib/whaler/command/run.rb
116
+ - lib/whaler/credentials_store.rb
62
117
  homepage: http://scalewhale.eu
63
118
  licenses:
64
119
  - MIT