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 +4 -4
- data/bin/whaler +10 -0
- data/lib/whaler/api/actions/login.rb +8 -0
- data/lib/whaler/api/actions/run.rb +10 -0
- data/lib/whaler/api/errors.rb +15 -0
- data/lib/whaler/api.rb +38 -0
- data/lib/whaler/auth.rb +55 -0
- data/lib/whaler/cli.rb +61 -0
- data/lib/whaler/command/login.rb +22 -0
- data/lib/whaler/command/run.rb +21 -0
- data/lib/whaler/command.rb +20 -0
- data/lib/whaler/credentials_store.rb +51 -0
- data/lib/whaler.rb +9 -0
- metadata +62 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbfca957958dc9ca8c9c9ba89cfa730be5cf4163
|
4
|
+
data.tar.gz: 8ed7262a6ce61c131c0564e9edb66a231e7e2041
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1359ea363869da55fede9c7a4dcb97cfce74823bc2db54b1b57b2fcbd3ab9d9d22ba87d5f071381b892e3ac85a435b9e4232643b6562e6da0c3e928a6855d1d0
|
7
|
+
data.tar.gz: 6564f31f655793ec01504697489e3bf8c176fe455cc7b12663f4e2c146a3bcd7949f89e76c03d9563b9a5bd6c8171fb63dae55df58b26397146b31da937c0036
|
data/bin/whaler
ADDED
@@ -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
|
data/lib/whaler/auth.rb
ADDED
@@ -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
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.
|
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:
|
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:
|
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:
|
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
|