whipped-cream 0.0.1pre1 → 0.0.1pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/whipped-cream.rb +9 -8
- data/lib/whipped-cream/cli.rb +12 -1
- data/lib/whipped-cream/deployer.rb +85 -0
- data/lib/whipped-cream/server.rb +6 -4
- data/lib/whipped-cream/version.rb +1 -1
- data/spec/lib/whipped-cream/cli_spec.rb +31 -6
- data/spec/lib/whipped-cream/deployer_spec.rb +56 -0
- data/spec/lib/whipped-cream/server_spec.rb +17 -3
- data/whipped-cream.gemspec +2 -0
- metadata +36 -1
data/lib/whipped-cream.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
1
|
+
require 'whipped-cream/builder'
|
2
|
+
require 'whipped-cream/button'
|
3
|
+
require 'whipped-cream/cli'
|
4
|
+
require 'whipped-cream/deployer'
|
5
|
+
require 'whipped-cream/plugin'
|
6
|
+
require 'whipped-cream/runner'
|
7
|
+
require 'whipped-cream/sensor'
|
8
|
+
require 'whipped-cream/server'
|
9
|
+
require 'whipped-cream/version'
|
data/lib/whipped-cream/cli.rb
CHANGED
@@ -25,13 +25,24 @@ module WhippedCream
|
|
25
25
|
server.start
|
26
26
|
end
|
27
27
|
|
28
|
+
desc "deploy PLUGIN IP", "Deploy a plugin to a Pi"
|
29
|
+
def deploy(plugin_name, pi_address)
|
30
|
+
plugin_path = resolve_plugin(plugin_name)
|
31
|
+
|
32
|
+
deployer = Deployer.new(plugin_path, pi_address)
|
33
|
+
deployer.deploy
|
34
|
+
end
|
35
|
+
|
28
36
|
desc "start PLUGIN", "Start a plugin"
|
37
|
+
method_option :daemonize,
|
38
|
+
type: :boolean,
|
39
|
+
desc: "Run the server in the background"
|
29
40
|
def start(plugin_name)
|
30
41
|
plugin_path = resolve_plugin(plugin_name)
|
31
42
|
|
32
43
|
plugin = Plugin.from_file(plugin_path)
|
33
44
|
server = Server.new(plugin)
|
34
|
-
server.start
|
45
|
+
server.start(options)
|
35
46
|
end
|
36
47
|
|
37
48
|
no_tasks do
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'net/scp'
|
2
|
+
require 'net/ssh'
|
3
|
+
|
4
|
+
module WhippedCream
|
5
|
+
# Prepares a Pi for deployment, and deploys a plugin
|
6
|
+
class Deployer
|
7
|
+
attr_reader :plugin_filename, :pi_address
|
8
|
+
|
9
|
+
def initialize(plugin_filename, pi_address)
|
10
|
+
@plugin_filename = plugin_filename
|
11
|
+
@pi_address = pi_address
|
12
|
+
end
|
13
|
+
|
14
|
+
def deploy
|
15
|
+
bootstrap
|
16
|
+
copy_plugin
|
17
|
+
kill_all_plugins
|
18
|
+
run_plugin
|
19
|
+
end
|
20
|
+
|
21
|
+
def scp
|
22
|
+
@scp ||= Net::SCP.start(*connection_arguments)
|
23
|
+
end
|
24
|
+
|
25
|
+
def ssh
|
26
|
+
@ssh ||= Net::SSH.start(*connection_arguments)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def connection_arguments
|
32
|
+
[pi_address, 'pi', { password: 'raspberry' }]
|
33
|
+
end
|
34
|
+
|
35
|
+
def bootstrap
|
36
|
+
ssh_exec <<-SCRIPT
|
37
|
+
which ruby ||
|
38
|
+
time sudo apt-get install ruby -y
|
39
|
+
|
40
|
+
which runit ||
|
41
|
+
time sudo apt-get install runit -y
|
42
|
+
|
43
|
+
which whipped-cream ||
|
44
|
+
time sudo gem install whipped-cream --no-ri --no-rdoc --pre
|
45
|
+
|
46
|
+
mkdir -p ~/whipped-cream/
|
47
|
+
SCRIPT
|
48
|
+
end
|
49
|
+
|
50
|
+
def copy_plugin
|
51
|
+
scp_copy plugin_filename, "whipped-cream/#{plugin_filename}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def kill_all_plugins
|
55
|
+
ssh_exec 'sudo pkill -9 -f whipped-cream'
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_plugin
|
59
|
+
ssh_exec <<-SCRIPT
|
60
|
+
cd ~/whipped-cream
|
61
|
+
sudo whipped-cream start demo.rb
|
62
|
+
SCRIPT
|
63
|
+
end
|
64
|
+
|
65
|
+
def scp_copy(local, remote)
|
66
|
+
scp.upload! local, remote
|
67
|
+
end
|
68
|
+
|
69
|
+
def ssh_exec(command)
|
70
|
+
command = command.prepend("set -ex\n")
|
71
|
+
|
72
|
+
ssh.open_channel do |channel|
|
73
|
+
channel.exec command do |process|
|
74
|
+
process.on_data do |_, data|
|
75
|
+
$stdout.print data
|
76
|
+
end
|
77
|
+
|
78
|
+
process.on_extended_data do |_, _, data|
|
79
|
+
$stderr.print data
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end.wait
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/whipped-cream/server.rb
CHANGED
@@ -9,11 +9,11 @@ module WhippedCream
|
|
9
9
|
@plugin = plugin
|
10
10
|
end
|
11
11
|
|
12
|
-
def start
|
12
|
+
def start(options = {})
|
13
13
|
ensure_routes_built
|
14
14
|
ensure_runner_started
|
15
15
|
|
16
|
-
start_web
|
16
|
+
start_web(options)
|
17
17
|
end
|
18
18
|
|
19
19
|
def runner
|
@@ -38,8 +38,10 @@ module WhippedCream
|
|
38
38
|
@routes_built ||= build_routes || true
|
39
39
|
end
|
40
40
|
|
41
|
-
def start_web
|
42
|
-
|
41
|
+
def start_web(options = {})
|
42
|
+
options = options.merge({ app: web, port: port })
|
43
|
+
|
44
|
+
Rack::Server.start options
|
43
45
|
end
|
44
46
|
|
45
47
|
def build_routes
|
@@ -15,6 +15,7 @@ describe WhippedCream::CLI do
|
|
15
15
|
button "Open/Close", pin: 1
|
16
16
|
PLUGIN
|
17
17
|
}
|
18
|
+
let(:pi_address) { "192.168.0.123" }
|
18
19
|
let(:tmpdir) { Dir.mktmpdir }
|
19
20
|
|
20
21
|
before do
|
@@ -33,20 +34,44 @@ describe WhippedCream::CLI do
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
describe "#
|
37
|
-
it "
|
38
|
-
|
39
|
-
expect(cli).to receive(:help)
|
37
|
+
describe "#deploy" do
|
38
|
+
it "deploys a plugin to a Pi" do
|
39
|
+
deployer_double = double(WhippedCream::Deployer)
|
40
40
|
|
41
|
-
|
41
|
+
expect(WhippedCream::Deployer).to receive(:new) { deployer_double }
|
42
|
+
expect(deployer_double).to receive(:deploy)
|
43
|
+
|
44
|
+
cli.deploy(plugin_filename, pi_address)
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
48
|
describe "#start" do
|
49
|
+
let(:server_double) { double(WhippedCream::Server) }
|
50
|
+
|
46
51
|
it "starts a server for the plugin" do
|
47
|
-
expect(
|
52
|
+
expect(WhippedCream::Server).to receive(:new) { server_double }
|
53
|
+
expect(server_double).to receive(:start)
|
48
54
|
|
49
55
|
cli.start(plugin_filename)
|
50
56
|
end
|
57
|
+
|
58
|
+
context "with --daemonize" do
|
59
|
+
it "starts a server in the background" do
|
60
|
+
expect(WhippedCream::Server).to receive(:new) { server_double }
|
61
|
+
expect(server_double).to receive(:start).with(daemonize: true)
|
62
|
+
|
63
|
+
cli.options = { daemonize: true }
|
64
|
+
cli.start(plugin_filename)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#usage" do
|
70
|
+
it "displays a banner and help" do
|
71
|
+
expect(cli).to receive(:puts).exactly(2).times
|
72
|
+
expect(cli).to receive(:help)
|
73
|
+
|
74
|
+
cli.usage
|
75
|
+
end
|
51
76
|
end
|
52
77
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WhippedCream::Deployer do
|
4
|
+
subject { deployer }
|
5
|
+
let(:deployer) { described_class.new(plugin_filename, pi_address) }
|
6
|
+
|
7
|
+
let(:plugin_filename) { 'demo.rb' }
|
8
|
+
let(:pi_address) { '192.168.0.123' }
|
9
|
+
|
10
|
+
let(:net_ssh_double) {
|
11
|
+
double(Net::SSH, exec!: nil, open_channel: double(wait: nil))
|
12
|
+
}
|
13
|
+
|
14
|
+
before do
|
15
|
+
deployer.stub :scp_copy
|
16
|
+
deployer.stub :ssh_exec
|
17
|
+
end
|
18
|
+
|
19
|
+
its(:plugin_filename) { should eq(plugin_filename) }
|
20
|
+
its(:pi_address) { should eq(pi_address) }
|
21
|
+
|
22
|
+
describe "#scp" do
|
23
|
+
it "tries to connect with pi:raspberry" do
|
24
|
+
expect(Net::SCP).to receive(:start).with(
|
25
|
+
pi_address, 'pi', password: 'raspberry'
|
26
|
+
)
|
27
|
+
|
28
|
+
deployer.scp
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#ssh" do
|
33
|
+
it "tries to connect with pi:raspberry" do
|
34
|
+
expect(Net::SSH).to receive(:start).with(
|
35
|
+
pi_address, 'pi', password: 'raspberry'
|
36
|
+
)
|
37
|
+
|
38
|
+
deployer.ssh
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#deploy" do
|
43
|
+
subject(:deploy) { deployer.deploy }
|
44
|
+
|
45
|
+
it "bootstraps the Pi" do
|
46
|
+
expect(deployer).to receive(:bootstrap)
|
47
|
+
expect(deployer).to receive(:copy_plugin)
|
48
|
+
expect(deployer).to receive(:kill_all_plugins)
|
49
|
+
expect(deployer).to receive(:run_plugin)
|
50
|
+
|
51
|
+
deploy
|
52
|
+
end
|
53
|
+
|
54
|
+
# xit "prompts the user for a password on failure"
|
55
|
+
end
|
56
|
+
end
|
@@ -31,9 +31,23 @@ describe WhippedCream::Server do
|
|
31
31
|
).to be_true
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
describe "#start" do
|
35
|
+
it "starts a Rack server" do
|
36
|
+
expect(Rack::Server).to receive(:start).with(
|
37
|
+
app: WhippedCream::Server::Web, port: 8080
|
38
|
+
)
|
36
39
|
|
37
|
-
|
40
|
+
server.start
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with daemonize: true" do
|
44
|
+
it "starts the Sinatra application" do
|
45
|
+
expect(Rack::Server).to receive(:start).with(
|
46
|
+
app: WhippedCream::Server::Web, port: 8080, daemonize: true
|
47
|
+
)
|
48
|
+
|
49
|
+
server.start(daemonize: true)
|
50
|
+
end
|
51
|
+
end
|
38
52
|
end
|
39
53
|
end
|
data/whipped-cream.gemspec
CHANGED
@@ -22,6 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
|
23
23
|
spec.required_ruby_version = '>= 1.9.3'
|
24
24
|
|
25
|
+
spec.add_runtime_dependency 'net-scp'
|
26
|
+
spec.add_runtime_dependency 'net-ssh'
|
25
27
|
spec.add_runtime_dependency 'pi_piper'
|
26
28
|
spec.add_runtime_dependency 'sinatra'
|
27
29
|
spec.add_runtime_dependency 'thor'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whipped-cream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1pre2
|
5
5
|
prerelease: 5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,6 +11,38 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
date: 2013-10-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: net-scp
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: net-ssh
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
14
46
|
- !ruby/object:Gem::Dependency
|
15
47
|
name: pi_piper
|
16
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -165,6 +197,7 @@ files:
|
|
165
197
|
- lib/whipped-cream/button.rb
|
166
198
|
- lib/whipped-cream/cli.rb
|
167
199
|
- lib/whipped-cream/control.rb
|
200
|
+
- lib/whipped-cream/deployer.rb
|
168
201
|
- lib/whipped-cream/pi_piper.rb
|
169
202
|
- lib/whipped-cream/plugin.rb
|
170
203
|
- lib/whipped-cream/public/assets/application.css
|
@@ -179,6 +212,7 @@ files:
|
|
179
212
|
- spec/lib/whipped-cream/builder_spec.rb
|
180
213
|
- spec/lib/whipped-cream/button_spec.rb
|
181
214
|
- spec/lib/whipped-cream/cli_spec.rb
|
215
|
+
- spec/lib/whipped-cream/deployer_spec.rb
|
182
216
|
- spec/lib/whipped-cream/plugin_spec.rb
|
183
217
|
- spec/lib/whipped-cream/runner_spec.rb
|
184
218
|
- spec/lib/whipped-cream/sensor_spec.rb
|
@@ -218,6 +252,7 @@ test_files:
|
|
218
252
|
- spec/lib/whipped-cream/builder_spec.rb
|
219
253
|
- spec/lib/whipped-cream/button_spec.rb
|
220
254
|
- spec/lib/whipped-cream/cli_spec.rb
|
255
|
+
- spec/lib/whipped-cream/deployer_spec.rb
|
221
256
|
- spec/lib/whipped-cream/plugin_spec.rb
|
222
257
|
- spec/lib/whipped-cream/runner_spec.rb
|
223
258
|
- spec/lib/whipped-cream/sensor_spec.rb
|