dumbwaiter 0.3.2 → 0.3.3
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/Guardfile +1 -2
- data/README.md +9 -1
- data/lib/dumbwaiter/cli.rb +22 -4
- data/lib/dumbwaiter/instance.rb +18 -0
- data/lib/dumbwaiter/layer.rb +46 -0
- data/lib/dumbwaiter/stack.rb +5 -0
- data/lib/dumbwaiter/version.rb +1 -1
- data/spec/lib/dumbwaiter/cli_spec.rb +55 -4
- data/spec/lib/dumbwaiter/deployment_spec.rb +1 -0
- data/spec/lib/dumbwaiter/instance_spec.rb +22 -0
- data/spec/lib/dumbwaiter/layer_spec.rb +56 -0
- data/spec/lib/dumbwaiter/stack_spec.rb +3 -0
- metadata +7 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 037e1bc90c9a39f1a16951de02c0e95ea6fc0bcb
|
4
|
+
data.tar.gz: 3cf2330286cabb2f654b92a43458ff1177d75eab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3acb077db8d3514aff5babefb2e783f7fa0b92c70b2cd62240f518452821e4bfbcd8b4d9ef084ff0cba6a1b783ce1e3411b5dcd8587487c86f5e61b2d7e578e
|
7
|
+
data.tar.gz: e4ac64be955b4545a0dc4430509dc2541d61bec1b2836da0df9af3f161ce9050c5f9057e5d8063f4cbc032c65cd37e9c7aea6f0ca58aa30a447446f05c1d48e0
|
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -21,7 +21,7 @@ Dumbwaiter prescribes a very specific OpsWorks-centric workflow with the same
|
|
21
21
|
feeling of the Scalarium gem's CLI:
|
22
22
|
|
23
23
|
* Create OpsWorks stacks, layers and instances via YAML files
|
24
|
-
*
|
24
|
+
* Assign a stack's custom Chef cookbooks as a custom GitHub repo
|
25
25
|
* Create an application corresponding to a GitHub repo
|
26
26
|
* Run versioned deployments, rollbacks and one-off recipes
|
27
27
|
|
@@ -61,6 +61,10 @@ Deploy the "cinnamon" branch of the "syrup" application to the "Pancake" stack:
|
|
61
61
|
|
62
62
|
`dumbwaiter deploy Pancake syrup cinnamon`
|
63
63
|
|
64
|
+
List all the layers of the "Pizza" stack:
|
65
|
+
|
66
|
+
`dumbwaiter layers Pizza`
|
67
|
+
|
64
68
|
List the deployments on the "Maniacal Checklist" stack:
|
65
69
|
|
66
70
|
`dumbwaiter list "Maniacal Checklist"`
|
@@ -73,6 +77,10 @@ Roll back the "Snowman" stack's "dandruff" application:
|
|
73
77
|
|
74
78
|
`dumbwaiter rollback Snowman dandruff`
|
75
79
|
|
80
|
+
Run the sneakers recipe on all the angsty instances of the "Documentarian" stack:
|
81
|
+
|
82
|
+
`dumbwaiter run_recipe Documentarian angsty sneakers`
|
83
|
+
|
76
84
|
List the stacks and apps in your OpsWorks environment:
|
77
85
|
|
78
86
|
`dumbwaiter stacks`
|
data/lib/dumbwaiter/cli.rb
CHANGED
@@ -5,7 +5,7 @@ require "dumbwaiter/stack"
|
|
5
5
|
|
6
6
|
module Dumbwaiter
|
7
7
|
class Cli < Thor
|
8
|
-
desc "deploy
|
8
|
+
desc "deploy STACK APP GIT_REF", "Deploy an application revision"
|
9
9
|
def deploy(stack_name, app_name, revision)
|
10
10
|
stack = Stack.find(stack_name)
|
11
11
|
app = App.find(stack, app_name)
|
@@ -14,12 +14,12 @@ module Dumbwaiter
|
|
14
14
|
raise Thor::Error.new(e.message)
|
15
15
|
end
|
16
16
|
|
17
|
-
desc "list
|
17
|
+
desc "list STACK", "List all the deployments for a stack"
|
18
18
|
def list(stack_name)
|
19
19
|
stack = Stack.find(stack_name)
|
20
20
|
|
21
21
|
deployments = stack.deployments.select do |deployment|
|
22
|
-
%w(rollback deploy update_custom_cookbooks).include?(deployment.command_name)
|
22
|
+
%w(rollback deploy update_custom_cookbooks execute_recipes).include?(deployment.command_name)
|
23
23
|
end
|
24
24
|
|
25
25
|
deployments.each do |deployment|
|
@@ -36,7 +36,7 @@ module Dumbwaiter
|
|
36
36
|
raise Thor::Error.new(e.message)
|
37
37
|
end
|
38
38
|
|
39
|
-
desc "rollback
|
39
|
+
desc "rollback STACK APP", "Roll back an application"
|
40
40
|
def rollback(stack_name, app_name)
|
41
41
|
stack = Stack.find(stack_name)
|
42
42
|
app = App.find(stack, app_name)
|
@@ -45,9 +45,27 @@ module Dumbwaiter
|
|
45
45
|
raise Thor::Error.new(e.message)
|
46
46
|
end
|
47
47
|
|
48
|
+
desc "run_recipe STACK LAYER RECIPE", "Run a recipe against a stack's layer"
|
49
|
+
def run_recipe(stack_name, layer_name, recipe)
|
50
|
+
stack = Stack.find(stack_name)
|
51
|
+
layer = Layer.find(stack, layer_name)
|
52
|
+
layer.run_recipe(recipe)
|
53
|
+
rescue Dumbwaiter::Stack::NotFound, Dumbwaiter::Layer::NotFound => e
|
54
|
+
raise Thor::Error.new(e.message)
|
55
|
+
end
|
56
|
+
|
48
57
|
desc "stacks", "List all the stacks"
|
49
58
|
def stacks
|
50
59
|
Stack.all.each { |stack| Kernel.puts("#{stack.name}: #{stack.apps.map(&:name).join(', ')}") }
|
51
60
|
end
|
61
|
+
|
62
|
+
desc "layers STACK", "List all the layers for a stack"
|
63
|
+
def layers(stack_name)
|
64
|
+
stack = Stack.find(stack_name)
|
65
|
+
layer_names = stack.layers.map(&:shortname)
|
66
|
+
Kernel.puts(layer_names.join(', '))
|
67
|
+
rescue Dumbwaiter::Stack::NotFound => e
|
68
|
+
raise Thor::Error.new(e.message)
|
69
|
+
end
|
52
70
|
end
|
53
71
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Dumbwaiter::Instance
|
2
|
+
attr_reader :layer, :opsworks_instance, :opsworks
|
3
|
+
|
4
|
+
def self.all(layer, opsworks = Aws::OpsWorks.new(region: "us-east-1"))
|
5
|
+
instances = opsworks.describe_instances(layer_id: layer.id).instances
|
6
|
+
instances.map { |instance| new(layer, instance, opsworks) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(layer, opsworks_instance, opsworks)
|
10
|
+
@layer = layer
|
11
|
+
@opsworks_instance = opsworks_instance
|
12
|
+
@opsworks = opsworks
|
13
|
+
end
|
14
|
+
|
15
|
+
def id
|
16
|
+
opsworks_instance.instance_id
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "dumbwaiter/instance"
|
2
|
+
|
3
|
+
class Dumbwaiter::Layer
|
4
|
+
attr_reader :stack, :opsworks_layer, :opsworks
|
5
|
+
|
6
|
+
class NotFound < Exception; end
|
7
|
+
|
8
|
+
def self.all(stack, opsworks = Aws::OpsWorks.new(region: "us-east-1"))
|
9
|
+
opsworks.describe_layers(stack_id: stack.id).layers.map { |layer| new(stack, layer, opsworks) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.find(stack, layer_name, opsworks = Aws::OpsWorks.new(region: "us-east-1"))
|
13
|
+
layer = all(stack, opsworks).detect { |layer| layer.shortname == layer_name }
|
14
|
+
raise NotFound.new("No layer found with name #{layer_name}") if layer.nil?
|
15
|
+
layer
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(stack, opsworks_layer, opsworks)
|
19
|
+
@stack = stack
|
20
|
+
@opsworks_layer = opsworks_layer
|
21
|
+
@opsworks = opsworks
|
22
|
+
end
|
23
|
+
|
24
|
+
def id
|
25
|
+
opsworks_layer.layer_id
|
26
|
+
end
|
27
|
+
|
28
|
+
def shortname
|
29
|
+
opsworks_layer.shortname
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_recipe(recipe)
|
33
|
+
opsworks.create_deployment(
|
34
|
+
stack_id: stack.id,
|
35
|
+
instance_ids: instances.map(&:id),
|
36
|
+
command: {
|
37
|
+
name: "execute_recipes",
|
38
|
+
args: {recipes: [recipe]}
|
39
|
+
}
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def instances
|
44
|
+
@instances ||= Dumbwaiter::Instance.all(self, opsworks)
|
45
|
+
end
|
46
|
+
end
|
data/lib/dumbwaiter/stack.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "dumbwaiter/app"
|
2
2
|
require "dumbwaiter/deployment"
|
3
|
+
require "dumbwaiter/layer"
|
3
4
|
|
4
5
|
class Dumbwaiter::Stack
|
5
6
|
attr_reader :opsworks, :opsworks_stack
|
@@ -37,6 +38,10 @@ class Dumbwaiter::Stack
|
|
37
38
|
@deployments ||= Dumbwaiter::Deployment.all(self, opsworks)
|
38
39
|
end
|
39
40
|
|
41
|
+
def layers
|
42
|
+
@layers ||= Dumbwaiter::Layer.all(self, opsworks)
|
43
|
+
end
|
44
|
+
|
40
45
|
def rechef
|
41
46
|
opsworks.create_deployment(stack_id: id, command: {name: "update_custom_cookbooks"})
|
42
47
|
end
|
data/lib/dumbwaiter/version.rb
CHANGED
@@ -2,6 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Dumbwaiter::Cli do
|
4
4
|
let(:fake_app) { double(:app, name: "reifel") }
|
5
|
+
let(:fake_layer) { double(:layer, shortname: "beans") }
|
5
6
|
let(:fake_stack) { double(:stack, name: "ducks", id: "wat", apps: [fake_app]) }
|
6
7
|
|
7
8
|
subject(:cli) { Dumbwaiter::Cli.new }
|
@@ -9,6 +10,7 @@ describe Dumbwaiter::Cli do
|
|
9
10
|
before do
|
10
11
|
Dumbwaiter::Stack.stub(all: [fake_stack])
|
11
12
|
Dumbwaiter::App.stub(all: [fake_app])
|
13
|
+
Dumbwaiter::Layer.stub(all: [fake_layer])
|
12
14
|
end
|
13
15
|
|
14
16
|
describe "#deploy" do
|
@@ -88,6 +90,15 @@ describe Dumbwaiter::Cli do
|
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
93
|
+
context "when the deployment is a recipe execution" do
|
94
|
+
let(:fake_deployment) { double(:deployment, command_name: "execute_recipes", to_log: "whee!") }
|
95
|
+
|
96
|
+
it "lists the deployment" do
|
97
|
+
Kernel.should_receive(:puts).with("whee!")
|
98
|
+
cli.list("ducks")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
91
102
|
context "when the deployment is something else" do
|
92
103
|
let(:fake_deployment) { double(:deployment, command_name: "gargle", to_log: "brblrgl") }
|
93
104
|
|
@@ -105,10 +116,20 @@ describe Dumbwaiter::Cli do
|
|
105
116
|
end
|
106
117
|
end
|
107
118
|
|
108
|
-
describe "#
|
109
|
-
|
110
|
-
|
111
|
-
|
119
|
+
describe "#layers" do
|
120
|
+
context "when the stack exists" do
|
121
|
+
before { fake_stack.stub(layers: [fake_layer]) }
|
122
|
+
|
123
|
+
it "lists the layers" do
|
124
|
+
Kernel.should_receive(:puts).with("beans")
|
125
|
+
cli.layers("ducks")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when the stack does not exist" do
|
130
|
+
it "blows up" do
|
131
|
+
expect { cli.layers("wat") }.to raise_error(Thor::Error)
|
132
|
+
end
|
112
133
|
end
|
113
134
|
end
|
114
135
|
|
@@ -126,4 +147,34 @@ describe Dumbwaiter::Cli do
|
|
126
147
|
end
|
127
148
|
end
|
128
149
|
end
|
150
|
+
|
151
|
+
describe "#run_recipe" do
|
152
|
+
context "when the stack exists" do
|
153
|
+
context "when the layer exists" do
|
154
|
+
it "runs the recipe on the layer" do
|
155
|
+
fake_layer.should_receive(:run_recipe).with("meatballs")
|
156
|
+
cli.run_recipe("ducks", "beans", "meatballs")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "when the layer does not exist" do
|
161
|
+
it "blows up" do
|
162
|
+
expect { cli.run_recipe("ducks", "brick", "meatballs") }.to raise_error(Thor::Error)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context "when the stack does not exist" do
|
168
|
+
it "blows up" do
|
169
|
+
expect { cli.run_recipe("toques", "beans", "meatballs") }.to raise_error(Thor::Error)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "#stacks" do
|
175
|
+
it "lists the stacks" do
|
176
|
+
Kernel.should_receive(:puts).with("ducks: reifel")
|
177
|
+
cli.stacks
|
178
|
+
end
|
179
|
+
end
|
129
180
|
end
|
@@ -38,6 +38,7 @@ describe Dumbwaiter::Deployment do
|
|
38
38
|
|
39
39
|
describe ".all" do
|
40
40
|
let(:fake_stack) { double(:stack, id: "pancakes") }
|
41
|
+
|
41
42
|
it "fetches all the deployments" do
|
42
43
|
fake_opsworks.should_receive(:describe_deployments).with(stack_id: "pancakes")
|
43
44
|
Dumbwaiter::Deployment.all(fake_stack, fake_opsworks).should have(1).app
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dumbwaiter::Instance do
|
4
|
+
let(:fake_stack) { double(:stack, id: "pancakes") }
|
5
|
+
let(:fake_layer) { double(:layer, id: "pinto", stack: fake_stack) }
|
6
|
+
|
7
|
+
let(:fake_instance) { double(:instance, instance_id: "dragons") }
|
8
|
+
let(:fake_instances) { double(:instances, instances: [fake_instance]) }
|
9
|
+
let(:fake_opsworks) { double(:opsworks, describe_instances: fake_instances) }
|
10
|
+
|
11
|
+
subject(:instance) { Dumbwaiter::Instance.new(fake_layer, fake_instance, fake_opsworks) }
|
12
|
+
|
13
|
+
its(:opsworks_instance) { should == fake_instance }
|
14
|
+
its(:id) { should == "dragons" }
|
15
|
+
|
16
|
+
describe ".all" do
|
17
|
+
it "fetches all the instances" do
|
18
|
+
fake_opsworks.should_receive(:describe_instances).with(layer_id: "pinto")
|
19
|
+
Dumbwaiter::Instance.all(fake_layer, fake_opsworks).should have(1).instance
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dumbwaiter::Layer do
|
4
|
+
let(:fake_stack) { double(:stack, id: "pancakes") }
|
5
|
+
let(:fake_layer) { double(:layer, shortname: "meaty", layer_id: "pinto") }
|
6
|
+
let(:fake_layers) { double(:layers, layers: [fake_layer]) }
|
7
|
+
let(:fake_instance) { double(:instance, id: "dragons") }
|
8
|
+
let(:fake_instances) { double(:instances, instances: [fake_instance]) }
|
9
|
+
let(:fake_opsworks) { double(:opsworks, describe_layers: fake_layers, describe_instances: fake_instances) }
|
10
|
+
|
11
|
+
before do
|
12
|
+
Dumbwaiter::Instance.stub(all: [fake_instance])
|
13
|
+
end
|
14
|
+
|
15
|
+
subject(:layer) { Dumbwaiter::Layer.new(fake_stack, fake_layer, fake_opsworks) }
|
16
|
+
|
17
|
+
its(:opsworks_layer) { should == fake_layer }
|
18
|
+
its(:id) { should == "pinto" }
|
19
|
+
its(:shortname) { should == "meaty" }
|
20
|
+
|
21
|
+
its(:instances) { should == [fake_instance] }
|
22
|
+
|
23
|
+
describe ".all" do
|
24
|
+
it "fetches all the deployments" do
|
25
|
+
fake_opsworks.should_receive(:describe_layers).with(stack_id: "pancakes")
|
26
|
+
Dumbwaiter::Layer.all(fake_stack, fake_opsworks).should have(1).layer
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".find" do
|
31
|
+
context "when the layer exists" do
|
32
|
+
it "finds the layer by name" do
|
33
|
+
Dumbwaiter::Layer.find(fake_stack, "meaty", fake_opsworks).shortname.should == "meaty"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when the layer does not exist" do
|
38
|
+
it "blows up" do
|
39
|
+
expect {
|
40
|
+
Dumbwaiter::Layer.find(fake_stack, "brick", fake_opsworks)
|
41
|
+
}.to raise_error(Dumbwaiter::Layer::NotFound)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#run_recipe" do
|
47
|
+
it "executes a recipe" do
|
48
|
+
fake_opsworks.should_receive(:create_deployment) do |params|
|
49
|
+
params[:stack_id].should == "pancakes"
|
50
|
+
params[:instance_ids].should == ["dragons"]
|
51
|
+
params[:command].should == {name: "execute_recipes", args: {recipes: ["meatballs"]}}
|
52
|
+
end
|
53
|
+
layer.run_recipe("meatballs")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -6,12 +6,14 @@ describe Dumbwaiter::Stack do
|
|
6
6
|
let(:fake_opsworks) { double(:opsworks, describe_stacks: fake_stacks) }
|
7
7
|
let(:fake_app) { double(:app) }
|
8
8
|
let(:fake_deployment) { double(:deployment) }
|
9
|
+
let(:fake_layer) { double(:layer) }
|
9
10
|
|
10
11
|
subject(:stack) { Dumbwaiter::Stack.new(fake_stack, fake_opsworks) }
|
11
12
|
|
12
13
|
before do
|
13
14
|
Dumbwaiter::App.stub(all: [fake_app])
|
14
15
|
Dumbwaiter::Deployment.stub(all: [fake_deployment])
|
16
|
+
Dumbwaiter::Layer.stub(all: [fake_layer])
|
15
17
|
end
|
16
18
|
|
17
19
|
its(:opsworks_stack) { should == fake_stack }
|
@@ -20,6 +22,7 @@ describe Dumbwaiter::Stack do
|
|
20
22
|
|
21
23
|
its(:apps) { should == [fake_app] }
|
22
24
|
its(:deployments) { should == [fake_deployment] }
|
25
|
+
its(:layers) { should == [fake_layer] }
|
23
26
|
|
24
27
|
describe ".all" do
|
25
28
|
it "fetches all the stacks" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dumbwaiter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Doc Ritezel
|
@@ -118,6 +118,8 @@ files:
|
|
118
118
|
- lib/dumbwaiter/cli.rb
|
119
119
|
- lib/dumbwaiter/deployment.rb
|
120
120
|
- lib/dumbwaiter/deployment_custom_json.rb
|
121
|
+
- lib/dumbwaiter/instance.rb
|
122
|
+
- lib/dumbwaiter/layer.rb
|
121
123
|
- lib/dumbwaiter/stack.rb
|
122
124
|
- lib/dumbwaiter/version.rb
|
123
125
|
- script/ci.sh
|
@@ -125,6 +127,8 @@ files:
|
|
125
127
|
- spec/lib/dumbwaiter/cli_spec.rb
|
126
128
|
- spec/lib/dumbwaiter/deployment_custom_json_spec.rb
|
127
129
|
- spec/lib/dumbwaiter/deployment_spec.rb
|
130
|
+
- spec/lib/dumbwaiter/instance_spec.rb
|
131
|
+
- spec/lib/dumbwaiter/layer_spec.rb
|
128
132
|
- spec/lib/dumbwaiter/stack_spec.rb
|
129
133
|
- spec/spec_helper.rb
|
130
134
|
homepage: https://github.com/minifast/dumbwaiter
|
@@ -156,5 +160,7 @@ test_files:
|
|
156
160
|
- spec/lib/dumbwaiter/cli_spec.rb
|
157
161
|
- spec/lib/dumbwaiter/deployment_custom_json_spec.rb
|
158
162
|
- spec/lib/dumbwaiter/deployment_spec.rb
|
163
|
+
- spec/lib/dumbwaiter/instance_spec.rb
|
164
|
+
- spec/lib/dumbwaiter/layer_spec.rb
|
159
165
|
- spec/lib/dumbwaiter/stack_spec.rb
|
160
166
|
- spec/spec_helper.rb
|