shelly 0.0.1 → 0.0.2
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.
- data/Guardfile +5 -0
- data/README.md +6 -0
- data/Rakefile +6 -0
- data/bin/shelly +3 -0
- data/lib/core_ext/object.rb +5 -0
- data/lib/shelly.rb +5 -2
- data/lib/shelly/cli.rb +33 -0
- data/lib/shelly/client.rb +78 -0
- data/lib/shelly/user.rb +47 -0
- data/lib/shelly/version.rb +1 -1
- data/shelly.gemspec +11 -4
- data/spec/helpers.rb +7 -0
- data/spec/input_faker.rb +19 -0
- data/spec/io_ext.rb +5 -0
- data/spec/shelly/cli_spec.rb +92 -0
- data/spec/shelly/client_spec.rb +151 -0
- data/spec/shelly/user_spec.rb +70 -0
- data/spec/spec_helper.rb +11 -0
- metadata +168 -10
data/Guardfile
ADDED
data/README.md
ADDED
data/Rakefile
CHANGED
data/bin/shelly
ADDED
data/lib/shelly.rb
CHANGED
data/lib/shelly/cli.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "shelly"
|
2
|
+
|
3
|
+
module Shelly
|
4
|
+
class CLI < Thor
|
5
|
+
include Thor::Actions
|
6
|
+
autoload :User, "shelly/user"
|
7
|
+
|
8
|
+
map %w(-v --version) => :version
|
9
|
+
desc "version", "Displays shelly version"
|
10
|
+
def version
|
11
|
+
say "shelly version #{Shelly::VERSION}"
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "register", "Registers new user at Shelly Cloud"
|
15
|
+
def register
|
16
|
+
email_question = User.guess_email.blank? ? "Email:" : "Email (default #{User.guess_email}):"
|
17
|
+
email = ask(email_question)
|
18
|
+
email = User.guess_email if email.blank?
|
19
|
+
password = ask("Password:")
|
20
|
+
|
21
|
+
if email.blank? or password.blank?
|
22
|
+
say "Email and password can't be blank" and exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
user = User.new(email, password)
|
26
|
+
say "Check you mailbox for email confirmation" if user.register
|
27
|
+
rescue Client::APIError => e
|
28
|
+
if e.message == "Validation Failed"
|
29
|
+
e.errors.each { |error| say "#{error.first} #{error.last}" }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "rest_client"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module Shelly
|
5
|
+
class Client
|
6
|
+
class UnauthorizedException < Exception; end
|
7
|
+
class UnsupportedResponseException < Exception; end
|
8
|
+
class APIError < Exception
|
9
|
+
def initialize(response)
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
|
13
|
+
def message
|
14
|
+
@response["message"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def errors
|
18
|
+
@response["errors"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(email = nil, password = nil)
|
23
|
+
@email = email
|
24
|
+
@password = password
|
25
|
+
end
|
26
|
+
|
27
|
+
def api_url
|
28
|
+
ENV["SHELLY_URL"] || "https://admin.winniecloud.com/apiv2"
|
29
|
+
end
|
30
|
+
|
31
|
+
def register_user(email, password)
|
32
|
+
post('/users', :user => {:email => email, :password => password})
|
33
|
+
end
|
34
|
+
|
35
|
+
def post(path, params = {})
|
36
|
+
request(path, :post, params)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get(path)
|
40
|
+
request(path, :get)
|
41
|
+
end
|
42
|
+
|
43
|
+
def request(path, method, params = {})
|
44
|
+
unless @email.blank? or @password.blank?
|
45
|
+
params.merge!(:email => @email, :password => @password)
|
46
|
+
end
|
47
|
+
|
48
|
+
RestClient::Request.execute(
|
49
|
+
:method => method,
|
50
|
+
:url => "#{api_url}#{path}",
|
51
|
+
:headers => headers,
|
52
|
+
:payload => params.to_json
|
53
|
+
) { |response, request| process_response(response) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def process_response(response)
|
57
|
+
raise UnauthorizedException.new if response.code == 302
|
58
|
+
if [404, 422, 500].include?(response.code)
|
59
|
+
error_details = JSON.parse(response.body)
|
60
|
+
raise APIError.new(error_details)
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
response.return!
|
65
|
+
JSON.parse(response.body)
|
66
|
+
rescue RestClient::RequestFailed => e
|
67
|
+
raise UnauthorizedException.new if e.http_code == 406
|
68
|
+
raise UnsupportedResponseException.new(e)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def headers
|
73
|
+
{:accept => :json,
|
74
|
+
:content_type => :json,
|
75
|
+
"shelly-version" => Shelly::VERSION}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/shelly/user.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Shelly
|
2
|
+
class User
|
3
|
+
attr_reader :email, :password
|
4
|
+
def initialize(email = nil, password = nil)
|
5
|
+
@email = email
|
6
|
+
@password = password
|
7
|
+
end
|
8
|
+
|
9
|
+
def register
|
10
|
+
client = Client.new
|
11
|
+
client.register_user(email, password)
|
12
|
+
save_credentials
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.guess_email
|
16
|
+
@@guess_email ||= IO.popen("git config --get user.email").read.strip
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_credentials
|
20
|
+
@email, @password = File.read(credentials_path).split("\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
def save_credentials
|
24
|
+
FileUtils.mkdir_p(config_dir) unless credentials_exists?
|
25
|
+
File.open(credentials_path, 'w') { |file| file << "#{email}\n#{password}" }
|
26
|
+
set_credentials_permissions
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
def config_dir
|
31
|
+
File.expand_path("~/.shelly")
|
32
|
+
end
|
33
|
+
|
34
|
+
def credentials_path
|
35
|
+
File.join(config_dir, "credentials")
|
36
|
+
end
|
37
|
+
|
38
|
+
def credentials_exists?
|
39
|
+
File.exists?(credentials_path)
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_credentials_permissions
|
43
|
+
FileUtils.chmod(0700, config_dir)
|
44
|
+
FileUtils.chmod(0600, credentials_path)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/shelly/version.rb
CHANGED
data/shelly.gemspec
CHANGED
@@ -12,13 +12,20 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.description = %q{Tool for managing applications and clouds at shellycloud.com}
|
13
13
|
|
14
14
|
s.rubyforge_project = "shelly"
|
15
|
+
s.add_development_dependency "rspec"
|
16
|
+
s.add_development_dependency "guard"
|
17
|
+
s.add_development_dependency "guard-rspec"
|
18
|
+
if RUBY_PLATFORM =~ /darwin/
|
19
|
+
s.add_development_dependency "growl_notify"
|
20
|
+
s.add_development_dependency "rb-fsevent"
|
21
|
+
end
|
22
|
+
s.add_development_dependency "fakefs"
|
23
|
+
s.add_runtime_dependency "thor"
|
24
|
+
s.add_runtime_dependency "rest-client"
|
25
|
+
s.add_runtime_dependency "json"
|
15
26
|
|
16
27
|
s.files = `git ls-files`.split("\n")
|
17
28
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
29
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
30
|
s.require_paths = ["lib"]
|
20
|
-
|
21
|
-
# specify any dependencies here; for example:
|
22
|
-
# s.add_development_dependency "rspec"
|
23
|
-
# s.add_runtime_dependency "rest-client"
|
24
31
|
end
|
data/spec/helpers.rb
ADDED
data/spec/input_faker.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class InputFaker
|
2
|
+
def initialize(strings)
|
3
|
+
@strings = strings
|
4
|
+
end
|
5
|
+
|
6
|
+
def gets
|
7
|
+
next_string = @strings.shift
|
8
|
+
# Uncomment the following line if you'd like to see the faked $stdin#gets
|
9
|
+
# puts "(DEBUG) Faking #gets with: #{next_string}"
|
10
|
+
next_string
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.with_fake_input(strings)
|
14
|
+
$stdin = new(strings)
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
$stdin = STDIN
|
18
|
+
end
|
19
|
+
end
|
data/spec/io_ext.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "shelly/cli"
|
3
|
+
require "shelly/user"
|
4
|
+
|
5
|
+
describe Shelly::CLI do
|
6
|
+
before do
|
7
|
+
@client = mock
|
8
|
+
@cli = Shelly::CLI.new
|
9
|
+
Shelly::Client.stub(:new).and_return(@client)
|
10
|
+
$stdout.stub(:puts)
|
11
|
+
$stdout.stub(:print)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#version" do
|
15
|
+
it "should return shelly's version" do
|
16
|
+
$stdout.should_receive(:puts).with("shelly version #{Shelly::VERSION}")
|
17
|
+
@cli.version
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#register" do
|
22
|
+
before do
|
23
|
+
Shelly::User.stub(:guess_email).and_return("")
|
24
|
+
@client.stub(:register_user)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should ask for email and password" do
|
28
|
+
$stdout.should_receive(:print).with("Email: ")
|
29
|
+
$stdout.should_receive(:print).with("Password: ")
|
30
|
+
fake_stdin(["better@example.com", "secret"]) do
|
31
|
+
@cli.register
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should suggest email and use it if user enters blank email" do
|
36
|
+
Shelly::User.stub(:guess_email).and_return("kate@example.com")
|
37
|
+
$stdout.should_receive(:print).with("Email (default kate@example.com): ")
|
38
|
+
@client.should_receive(:register_user).with("kate@example.com", "secret")
|
39
|
+
fake_stdin(["", "secret"]) do
|
40
|
+
@cli.register
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should use email provided by user" do
|
45
|
+
@client.should_receive(:register_user).with("better@example.com", "secret")
|
46
|
+
fake_stdin(["better@example.com", "secret"]) do
|
47
|
+
@cli.register
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should exit with message if email is blank" do
|
52
|
+
Shelly::User.stub(:guess_email).and_return("")
|
53
|
+
$stdout.should_receive(:puts).with("Email and password can't be blank")
|
54
|
+
lambda do
|
55
|
+
fake_stdin(["", "only-pass"]) do
|
56
|
+
@cli.register
|
57
|
+
end
|
58
|
+
end.should raise_error(SystemExit)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should exit with message if password is blank" do
|
62
|
+
$stdout.should_receive(:puts).with("Email and password can't be blank")
|
63
|
+
lambda do
|
64
|
+
fake_stdin(["better@example.com", ""]) do
|
65
|
+
@cli.register
|
66
|
+
end
|
67
|
+
end.should raise_error(SystemExit)
|
68
|
+
end
|
69
|
+
|
70
|
+
context "on successful registration" do
|
71
|
+
it "should notify user about email verification" do
|
72
|
+
@client.stub(:register_user).and_return(true)
|
73
|
+
$stdout.should_receive(:puts).with("Check you mailbox for email confirmation")
|
74
|
+
fake_stdin(["kate@example.com", "pass"]) do
|
75
|
+
@cli.register
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "on unsuccessful registration" do
|
81
|
+
it "should notify user about errors" do
|
82
|
+
response = {"message" => "Validation Failed", "errors" => [["email", "has been already taken"]]}
|
83
|
+
exception = Shelly::Client::APIError.new(response)
|
84
|
+
@client.stub(:register_user).and_raise(exception)
|
85
|
+
$stdout.should_receive(:puts).with("email has been already taken")
|
86
|
+
fake_stdin(["kate@example.com", "pass"]) do
|
87
|
+
@cli.register
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Shelly::Client do
|
4
|
+
before do
|
5
|
+
ENV['SHELLY_URL'] = nil
|
6
|
+
@client = Shelly::Client.new("bob@example.com", "secret")
|
7
|
+
RestClient::Request.stub!(:execute)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#api_url" do
|
11
|
+
context "env SHELLY_URL is not set" do
|
12
|
+
it "should return default API URL" do
|
13
|
+
ENV['SHELLY_URL'].should be_nil
|
14
|
+
@client.api_url.should == "https://admin.winniecloud.com/apiv2"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "env variable SHELLY_URL is set" do
|
19
|
+
it "should return value of env variable SHELLY_URL" do
|
20
|
+
ENV['SHELLY_URL'] = "https://example.com/api"
|
21
|
+
@client.api_url.should == "https://example.com/api"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#request" do
|
27
|
+
it "should make a request to given URL" do
|
28
|
+
RestClient::Request.should_receive(:execute).with(
|
29
|
+
request_parameters("/account", :get)
|
30
|
+
)
|
31
|
+
@client.request("/account", :get)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should include provided parameters in the request" do
|
35
|
+
RestClient::Request.should_receive(:execute).with(
|
36
|
+
request_parameters("/account", :post, {:name => "test"})
|
37
|
+
)
|
38
|
+
@client.request("/account", :post, :name => "test")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should include user credentials in the request parameters" do
|
42
|
+
@client = Shelly::Client.new("megan-fox@example.com", "secret")
|
43
|
+
RestClient::Request.should_receive(:execute).with(
|
44
|
+
request_parameters("/account", :get, {:email => "megan-fox@example.com", :password => "secret"})
|
45
|
+
)
|
46
|
+
@client.request("/account", :get)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not include user credentials when they are blank" do
|
50
|
+
@client = Shelly::Client.new
|
51
|
+
RestClient::Request.should_receive(:execute).with(
|
52
|
+
:method => :get,
|
53
|
+
:url => "https://admin.winniecloud.com/apiv2/account",
|
54
|
+
:headers => {:accept => :json, :content_type => :json, "shelly-version" => Shelly::VERSION},
|
55
|
+
:payload => "{}"
|
56
|
+
)
|
57
|
+
@client.request("/account", :get)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should pass response to process_response method" do
|
61
|
+
response = mock(RestClient::Response)
|
62
|
+
request = mock(RestClient::Request)
|
63
|
+
@client.should_receive(:process_response).with(response)
|
64
|
+
RestClient::Request.should_receive(:execute).with(
|
65
|
+
request_parameters("/account", :get)
|
66
|
+
).and_yield(response, request)
|
67
|
+
|
68
|
+
@client.request("/account", :get)
|
69
|
+
end
|
70
|
+
|
71
|
+
def request_parameters(path, method, payload = {})
|
72
|
+
{:method => method,
|
73
|
+
:url => "https://admin.winniecloud.com/apiv2#{path}",
|
74
|
+
:headers => {:accept => :json, :content_type => :json, "shelly-version" => Shelly::VERSION},
|
75
|
+
:payload => ({:email => "bob@example.com", :password => "secret"}.merge(payload)).to_json}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#process_response" do
|
80
|
+
before do
|
81
|
+
@response = mock(RestClient::Response, :code => 200, :body => "{}", :return! => nil)
|
82
|
+
@request = mock(RestClient::Request)
|
83
|
+
RestClient::Request.stub(:execute).and_yield(@response, @request)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not follow redirections" do
|
87
|
+
@response.should_receive(:return!)
|
88
|
+
@client.get('/account')
|
89
|
+
end
|
90
|
+
|
91
|
+
context "on 302 response code" do
|
92
|
+
it "should raise UnauthorizedException" do
|
93
|
+
@response.stub(:code).and_return(302)
|
94
|
+
lambda {
|
95
|
+
@client.get("/account")
|
96
|
+
}.should raise_error(Shelly::Client::UnauthorizedException)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "on 406 response code" do
|
101
|
+
it "should raise UnauthorizedException" do
|
102
|
+
exception = RestClient::RequestFailed.new
|
103
|
+
exception.stub(:http_code).and_return(406)
|
104
|
+
@response.should_receive(:return!).and_raise(exception)
|
105
|
+
|
106
|
+
lambda {
|
107
|
+
@client.get("/account")
|
108
|
+
}.should raise_error(Shelly::Client::UnauthorizedException)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
%w(404 422 500).each do |code|
|
113
|
+
context "on #{code} response code" do
|
114
|
+
it "should raise APIError" do
|
115
|
+
@response.stub(:code).and_return(code.to_i)
|
116
|
+
@response.stub(:body).and_return({"message" => "random error happened"}.to_json)
|
117
|
+
|
118
|
+
lambda {
|
119
|
+
@client.post("/api/apps/flower/command", :body => "puts User.count")
|
120
|
+
}.should raise_error(Shelly::Client::APIError, "random error happened")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "on unsupported response code" do
|
126
|
+
it "should raise UnsupportedResponseException exception" do
|
127
|
+
exception = RestClient::RequestFailed.new
|
128
|
+
exception.stub(:http_code).and_return(409)
|
129
|
+
@response.should_receive(:return!).and_raise(exception)
|
130
|
+
|
131
|
+
lambda {
|
132
|
+
@client.get("/account")
|
133
|
+
}.should raise_error(Shelly::Client::UnsupportedResponseException)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#get" do
|
139
|
+
it "should make GET request to given path" do
|
140
|
+
@client.should_receive(:request).with("/account", :get)
|
141
|
+
@client.get("/account")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "#post" do
|
146
|
+
it "should make POST request to given path with parameters" do
|
147
|
+
@client.should_receive(:request).with("/account", :post, :name => "pink-one")
|
148
|
+
@client.post("/account", :name => "pink-one")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "shelly/user"
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Shelly::User do
|
5
|
+
include FakeFS::SpecHelpers
|
6
|
+
|
7
|
+
before do
|
8
|
+
@client = mock
|
9
|
+
Shelly::Client.stub(:new).and_return(@client)
|
10
|
+
@user = Shelly::User.new("bob@example.com", "secret")
|
11
|
+
@user.stub(:set_credentials_permissions)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".guess_email" do
|
15
|
+
it "should return user email fetched from git config" do
|
16
|
+
io = mock(:read => "boby@example.com\n")
|
17
|
+
IO.should_receive(:popen).with("git config --get user.email").and_return(io)
|
18
|
+
Shelly::User.guess_email.should == "boby@example.com"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#register" do
|
23
|
+
before do
|
24
|
+
@client.stub(:register_user)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should register user at Shelly Cloud" do
|
28
|
+
@client.should_receive(:register_user).with("bob@example.com", "secret")
|
29
|
+
@user.register
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should save credentials after successful registration" do
|
33
|
+
@user.should_receive(:save_credentials)
|
34
|
+
@user.register
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#save_credentials" do
|
39
|
+
it "should save credentials to file" do
|
40
|
+
File.exists?("~/.shelly/credentials").should be_false
|
41
|
+
@user.save_credentials
|
42
|
+
File.read("~/.shelly/credentials").should == "bob@example.com\nsecret"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should create config_dir if doesn't exist" do
|
46
|
+
File.exists?("~/.shelly").should be_false
|
47
|
+
@user.save_credentials
|
48
|
+
File.exists?("~/.shelly").should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should set proper permissions on config_dir and credentials file" do
|
52
|
+
user = Shelly::User.new("bob@example.com", "secret")
|
53
|
+
FileUtils.should_receive(:chmod).with(0700, File.expand_path("~/.shelly"))
|
54
|
+
FileUtils.should_receive(:chmod).with(0600, File.expand_path("~/.shelly/credentials"))
|
55
|
+
user.save_credentials
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#load_credentials" do
|
60
|
+
it "should load credentials from file" do
|
61
|
+
config_dir = File.expand_path("~/.shelly")
|
62
|
+
FileUtils.mkdir_p(config_dir)
|
63
|
+
File.open(File.join(config_dir, "credentials"), "w") { |f| f << "superman@example.com\nkal-el" }
|
64
|
+
user = Shelly::User.new
|
65
|
+
user.load_credentials
|
66
|
+
user.email.should == "superman@example.com"
|
67
|
+
user.password.should == "kal-el"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shelly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
6
11
|
platform: ruby
|
7
12
|
authors:
|
8
13
|
- Shelly Cloud team
|
@@ -10,14 +15,140 @@ autorequire:
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2011-09-
|
14
|
-
|
15
|
-
|
18
|
+
date: 2011-09-13 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: guard
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: guard-rspec
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: growl_notify
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: rb-fsevent
|
79
|
+
prerelease: false
|
80
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
type: :development
|
90
|
+
version_requirements: *id005
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: fakefs
|
93
|
+
prerelease: false
|
94
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
hash: 3
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
version: "0"
|
103
|
+
type: :development
|
104
|
+
version_requirements: *id006
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
name: thor
|
107
|
+
prerelease: false
|
108
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
hash: 3
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
version: "0"
|
117
|
+
type: :runtime
|
118
|
+
version_requirements: *id007
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
name: rest-client
|
121
|
+
prerelease: false
|
122
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
type: :runtime
|
132
|
+
version_requirements: *id008
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: json
|
135
|
+
prerelease: false
|
136
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 3
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
version: "0"
|
145
|
+
type: :runtime
|
146
|
+
version_requirements: *id009
|
16
147
|
description: Tool for managing applications and clouds at shellycloud.com
|
17
148
|
email:
|
18
149
|
- support@shellycloud.com
|
19
|
-
executables:
|
20
|
-
|
150
|
+
executables:
|
151
|
+
- shelly
|
21
152
|
extensions: []
|
22
153
|
|
23
154
|
extra_rdoc_files: []
|
@@ -25,10 +156,25 @@ extra_rdoc_files: []
|
|
25
156
|
files:
|
26
157
|
- .gitignore
|
27
158
|
- Gemfile
|
159
|
+
- Guardfile
|
160
|
+
- README.md
|
28
161
|
- Rakefile
|
162
|
+
- bin/shelly
|
163
|
+
- lib/core_ext/object.rb
|
29
164
|
- lib/shelly.rb
|
165
|
+
- lib/shelly/cli.rb
|
166
|
+
- lib/shelly/client.rb
|
167
|
+
- lib/shelly/user.rb
|
30
168
|
- lib/shelly/version.rb
|
31
169
|
- shelly.gemspec
|
170
|
+
- spec/helpers.rb
|
171
|
+
- spec/input_faker.rb
|
172
|
+
- spec/io_ext.rb
|
173
|
+
- spec/shelly/cli_spec.rb
|
174
|
+
- spec/shelly/client_spec.rb
|
175
|
+
- spec/shelly/user_spec.rb
|
176
|
+
- spec/spec_helper.rb
|
177
|
+
has_rdoc: true
|
32
178
|
homepage: http://shellycloud.com
|
33
179
|
licenses: []
|
34
180
|
|
@@ -42,19 +188,31 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
188
|
requirements:
|
43
189
|
- - ">="
|
44
190
|
- !ruby/object:Gem::Version
|
191
|
+
hash: 3
|
192
|
+
segments:
|
193
|
+
- 0
|
45
194
|
version: "0"
|
46
195
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
196
|
none: false
|
48
197
|
requirements:
|
49
198
|
- - ">="
|
50
199
|
- !ruby/object:Gem::Version
|
200
|
+
hash: 3
|
201
|
+
segments:
|
202
|
+
- 0
|
51
203
|
version: "0"
|
52
204
|
requirements: []
|
53
205
|
|
54
206
|
rubyforge_project: shelly
|
55
|
-
rubygems_version: 1.
|
207
|
+
rubygems_version: 1.3.7
|
56
208
|
signing_key:
|
57
209
|
specification_version: 3
|
58
210
|
summary: Shelly Cloud command line tool
|
59
|
-
test_files:
|
60
|
-
|
211
|
+
test_files:
|
212
|
+
- spec/helpers.rb
|
213
|
+
- spec/input_faker.rb
|
214
|
+
- spec/io_ext.rb
|
215
|
+
- spec/shelly/cli_spec.rb
|
216
|
+
- spec/shelly/client_spec.rb
|
217
|
+
- spec/shelly/user_spec.rb
|
218
|
+
- spec/spec_helper.rb
|