opsicle 0.1.0 → 0.2.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.
Files changed (46) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +3 -0
  3. data/.travis.yml +6 -1
  4. data/Gemfile +3 -0
  5. data/Guardfile +5 -0
  6. data/README.markdown +44 -17
  7. data/bin/opsicle +36 -3
  8. data/lib/opsicle.rb +2 -3
  9. data/lib/opsicle/commands.rb +6 -0
  10. data/lib/opsicle/commands/deploy.rb +39 -0
  11. data/lib/opsicle/{list.rb → commands/list.rb} +0 -2
  12. data/lib/opsicle/{ssh.rb → commands/ssh.rb} +0 -3
  13. data/lib/opsicle/commands/ssh_key.rb +40 -0
  14. data/lib/opsicle/config.rb +1 -0
  15. data/lib/opsicle/deployment.rb +59 -0
  16. data/lib/opsicle/deployments.rb +22 -0
  17. data/lib/opsicle/monitor.rb +12 -0
  18. data/lib/opsicle/monitor/app.rb +147 -0
  19. data/lib/opsicle/monitor/panel.rb +98 -0
  20. data/lib/opsicle/monitor/panels/deployments.rb +42 -0
  21. data/lib/opsicle/monitor/panels/header.rb +48 -0
  22. data/lib/opsicle/monitor/panels/help.rb +33 -0
  23. data/lib/opsicle/monitor/screen.rb +83 -0
  24. data/lib/opsicle/monitor/spy/dataspyable.rb +19 -0
  25. data/lib/opsicle/monitor/spy/deployments.rb +53 -0
  26. data/lib/opsicle/monitor/subpanel.rb +55 -0
  27. data/lib/opsicle/monitor/translatable.rb +33 -0
  28. data/lib/opsicle/stack.rb +22 -0
  29. data/lib/opsicle/version.rb +1 -1
  30. data/opsicle.gemspec +1 -1
  31. data/spec/opsicle/client_spec.rb +6 -6
  32. data/spec/opsicle/commands/deploy_spec.rb +50 -0
  33. data/spec/opsicle/{list_spec.rb → commands/list_spec.rb} +7 -6
  34. data/spec/opsicle/commands/ssh_key_spec.rb +75 -0
  35. data/spec/opsicle/{ssh_spec.rb → commands/ssh_spec.rb} +24 -24
  36. data/spec/opsicle/config_spec.rb +12 -11
  37. data/spec/opsicle/monitor/app_spec.rb +63 -0
  38. data/spec/opsicle/monitor/panel_spec.rb +162 -0
  39. data/spec/opsicle/monitor/screen_spec.rb +121 -0
  40. data/spec/opsicle/monitor/spy/deployments_spec.rb +41 -0
  41. data/spec/opsicle/monitor/subpanel_spec.rb +199 -0
  42. data/spec/spec_helper.rb +2 -1
  43. metadata +44 -16
  44. data/Gemfile.lock +0 -75
  45. data/lib/opsicle/deploy.rb +0 -25
  46. data/spec/opsicle/deploy_spec.rb +0 -29
@@ -0,0 +1,162 @@
1
+ require "spec_helper"
2
+ require "opsicle/monitor/panel"
3
+ require "curses"
4
+
5
+
6
+ describe Opsicle::Monitor::Panel do
7
+
8
+ before do
9
+ @window = double
10
+
11
+ allow(Curses::Window).to receive(:new).and_return(@window)
12
+
13
+ @panel = Opsicle::Monitor::Panel.new(24, 80, 1, 2)
14
+ end
15
+
16
+ describe "#initialize" do
17
+ describe "required" do
18
+ it "sets height" do
19
+ expect(@panel.height).to equal(24)
20
+ end
21
+
22
+ it "sets width" do
23
+ expect(@panel.width).to equal(80)
24
+ end
25
+
26
+ it "sets top" do
27
+ expect(@panel.top).to equal(1)
28
+ end
29
+
30
+ it "sets left" do
31
+ expect(@panel.left).to equal(2)
32
+ end
33
+
34
+ it "defaults dividers" do
35
+ expect(@panel.dividers).to eq({
36
+ :left => '',
37
+ :right => '',
38
+ })
39
+ end
40
+
41
+ it "calculates divider_length" do
42
+ expect(@panel.divider_length).to equal(0)
43
+ end
44
+
45
+
46
+ it "sets up window with dimensions" do
47
+ expect(Curses::Window).to receive(:new).with(24,80,1,2)
48
+
49
+ Opsicle::Monitor::Panel.new(24, 80, 1, 2)
50
+ end
51
+
52
+ it "sets window" do
53
+ expect(@panel.instance_variable_get(:@window)).to eq(@window)
54
+ end
55
+ end
56
+
57
+ describe "optional" do
58
+ before do
59
+ @structure = [
60
+ [
61
+ [1, "busy:", -> { 1 + 3 }], # S(0,0)
62
+ [1, "retries:", 2], # S(0,1)
63
+ ],
64
+ [
65
+ [2, -> { 2 * 7 }, "long"], # S(1,0)
66
+ [1, -> { "1" + "4" }, -> { "dark" }], # S(1,1)
67
+ ],
68
+ ]
69
+
70
+ @panel = Opsicle::Monitor::Panel.new(24, 80, 1, 2, @structure,
71
+ :divider_l => '<',
72
+ :divider_r => '>'
73
+ )
74
+
75
+ @subpanels = @panel.instance_variable_get(:@subpanels)
76
+ end
77
+
78
+ it "sets dividers" do
79
+ expect(@panel.dividers).to eq({
80
+ :left => '<',
81
+ :right => '>',
82
+ })
83
+ end
84
+
85
+ it "calculates divider_length" do
86
+ expect(@panel.divider_length).to equal(2)
87
+ end
88
+
89
+ it "builds enough subpanels" do
90
+ expect(@subpanels.length).to equal(4)
91
+ end
92
+
93
+ it "builds S(0,0)" do
94
+ expect(@subpanels.count { |e|
95
+ e.height == 1 && e.width == 42 && e.top == 0 && e.left == 0 &&
96
+ e.data[:left] == "busy:" && e.data[:right].call == 4 &&
97
+ e.dividers[:left] == '' && e.dividers[:right] == '>' &&
98
+ e.content_width == 41
99
+ }).to equal(1)
100
+ end
101
+
102
+ it "builds S(0,1)" do
103
+ expect(@subpanels.count { |e|
104
+ e.height == 1 && e.width == 38 && e.top == 0 && e.left == 42 &&
105
+ e.data[:left] == "retries:" && e.data[:right] == 2 &&
106
+ e.dividers[:left] == '<' && e.dividers[:right] == '' &&
107
+ e.content_width == 37
108
+ }).to equal(1)
109
+ end
110
+
111
+ it "builds S(1,0)" do
112
+ expect(@subpanels.count { |e|
113
+ e.height == 1 && e.width == 56 && e.top == 1 && e.left == 0 &&
114
+ e.data[:left].call == 14 && e.data[:right] == "long" &&
115
+ e.dividers[:left] == '' && e.dividers[:right] == '>' &&
116
+ e.content_width == 55
117
+ }).to equal(1)
118
+ end
119
+
120
+ it "builds S(1,1)" do
121
+ expect(@subpanels.count { |e|
122
+ e.height == 1 && e.width == 24 && e.top == 1 && e.left == 56 &&
123
+ e.data[:left].call == "14" && e.data[:right].call == "dark" &&
124
+ e.dividers[:left] == '<' && e.dividers[:right] == '' &&
125
+ e.content_width == 23
126
+ }).to equal(1)
127
+ end
128
+ end
129
+ end
130
+
131
+ describe "#close" do
132
+ it "closes window" do
133
+ expect(@window).to receive(:close)
134
+
135
+ @panel.close
136
+ end
137
+ end
138
+
139
+ describe "#refresh" do
140
+ it "refreshes subpanels" do
141
+ allow(@window).to receive(:refresh)
142
+
143
+ @subpanel2 = double
144
+ expect(@subpanel2).to receive(:refresh)
145
+
146
+ @panel.instance_variable_set(:@subpanels, [@subpanel2])
147
+
148
+ @panel.refresh
149
+ end
150
+
151
+ it "refreshes window" do
152
+ @subpanel2 = double(:refresh => nil)
153
+
154
+ @panel.instance_variable_set(:@subpanels, [@subpanel2])
155
+
156
+ expect(@window).to receive(:refresh)
157
+
158
+ @panel.refresh
159
+ end
160
+ end
161
+
162
+ end
@@ -0,0 +1,121 @@
1
+ require "spec_helper"
2
+ require "opsicle/monitor/screen"
3
+ require "opsicle/monitor/panels/header"
4
+ require "opsicle/monitor/panels/deployments"
5
+ require "opsicle/monitor/panels/help"
6
+
7
+
8
+ describe Opsicle::Monitor::Screen do
9
+
10
+ before do
11
+
12
+ curses_test = double(
13
+ "Curses",
14
+ :init_screen => nil,
15
+ :close_screen => nil,
16
+ :nl => nil,
17
+ :noecho => nil,
18
+ :curs_set => nil,
19
+ :timeout= => nil,
20
+ :refresh => nil,
21
+ :lines => 24,
22
+ :cols => 80
23
+ )
24
+ stub_const "Curses", curses_test
25
+
26
+ @panel = double(
27
+ "@panel",
28
+ :close => nil,
29
+ :panel_main= => nil
30
+ )
31
+ @panel_d = @panel.dup
32
+ @panel_q = @panel.dup
33
+
34
+ allow(Opsicle::Monitor::Panels::Header).to receive(:new).and_return(@panel)
35
+ allow(Opsicle::Monitor::Panels::Deployments).to receive(:new).and_return(@panel_d)
36
+ allow(Opsicle::Monitor::Panels::Help).to receive(:new).and_return(@panel_h)
37
+
38
+ @screen = Opsicle::Monitor::Screen.new
39
+ end
40
+
41
+ describe "#initialize" do
42
+ it "inits screen" do
43
+ expect(Curses).to receive(:init_screen)
44
+
45
+ Opsicle::Monitor::Screen.new
46
+ end
47
+
48
+ it "sets height" do
49
+ expect(@screen.height).to equal(24)
50
+ end
51
+
52
+ it "sets width" do
53
+ expect(@screen.width).to equal(80)
54
+ end
55
+ end
56
+
57
+ describe "#close" do
58
+ it "closes screen" do
59
+ @screen.instance_variable_set(:@panels, { :panel => @panel })
60
+ expect(Curses).to receive(:close_screen)
61
+
62
+ @screen.close
63
+ end
64
+
65
+ it "closes panels" do
66
+ @panel2 = double
67
+ expect(@panel2).to receive(:close)
68
+
69
+ @screen.instance_variable_set(:@panels, { :panel2 => @panel2 })
70
+
71
+ @screen.close
72
+ end
73
+ end
74
+
75
+ describe "#refresh" do
76
+ it "refreshes panels" do
77
+ @panel2 = double
78
+ expect(@panel2).to receive(:refresh)
79
+
80
+ @screen.instance_variable_set(:@panels, { :panel2 => @panel2 })
81
+
82
+ @screen.refresh
83
+ end
84
+ end
85
+
86
+ describe "#next_key" do
87
+ it "gets next key" do
88
+ expect(Curses).to receive(:getch)
89
+
90
+ @screen.next_key
91
+ end
92
+ end
93
+
94
+ describe "#missized?" do
95
+ it "returns false when not missized" do
96
+ expect(@screen).to receive(:term_height).and_return(24)
97
+ expect(@screen).to receive(:term_width).and_return(80)
98
+
99
+ expect(@screen.missized?).to equal(false)
100
+
101
+ end
102
+
103
+ it "returns true when missized" do
104
+ expect(@screen).to receive(:term_height).and_return(21)
105
+ # Width isn't checked before height
106
+
107
+ expect(@screen.missized?).to equal(true)
108
+ end
109
+ end
110
+
111
+ describe "#panel_main=" do
112
+ before do
113
+ @panels = @screen.instance_variable_get(:@panels)
114
+ end
115
+
116
+ it "defaults panel_main to deployments" do
117
+ expect(@panels[:main]).to equal(@panel_d)
118
+ end
119
+ end
120
+
121
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'opsicle/deployments'
3
+ require 'opsicle/monitor/spy/dataspyable'
4
+ require 'opsicle/monitor/translatable'
5
+ require 'opsicle/monitor/spy/deployments'
6
+ require 'opsicle/monitor/app'
7
+
8
+ describe Opsicle::Monitor::Spy::Deployments do
9
+ before do
10
+ @deployments = double(:data => {})
11
+
12
+ expect(Opsicle::Deployments).to receive(:new).and_return(@deployments)
13
+
14
+ @subject = Opsicle::Monitor::Spy::Deployments.new
15
+ end
16
+
17
+ describe "#user_from_arn" do
18
+ it "parses a normal user string" do
19
+ result = @subject.user_from_arn("arn:aws:iam::465198754621:user/chris.arcand")
20
+ expect(result).to eq("chris.arcand")
21
+ end
22
+
23
+ it "parses a root user string" do
24
+ result = @subject.user_from_arn("arn:aws:iam::465198754621:root")
25
+ expect(result).to eq("root")
26
+ end
27
+
28
+ it "handles an unknown string gracefully" do
29
+ result = @subject.user_from_arn("Ugly string")
30
+ expect(result).to eq("Ugly string")
31
+ end
32
+
33
+ it "handles a nil or empty string gracefully" do
34
+ nilstring = @subject.user_from_arn(nil)
35
+ emptystring = @subject.user_from_arn("")
36
+
37
+ expect(nilstring).to eq("")
38
+ expect(nilstring).to eq("")
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,199 @@
1
+ require "spec_helper"
2
+ require "opsicle/monitor/subpanel"
3
+
4
+
5
+ describe Opsicle::Monitor::Subpanel do
6
+
7
+ describe "#initialize" do
8
+ describe "required" do
9
+ before do
10
+ @window = double
11
+
12
+ @subpanel = Opsicle::Monitor::Subpanel.new(@window, 24, 80, 1, 2)
13
+ end
14
+
15
+ it "sets window" do
16
+ expect(@subpanel.instance_variable_get(:@window)).to equal(@window)
17
+ end
18
+
19
+ it "sets height" do
20
+ expect(@subpanel.height).to equal(24)
21
+ end
22
+
23
+ it "sets width" do
24
+ expect(@subpanel.width).to equal(80)
25
+ end
26
+
27
+ it "sets top" do
28
+ expect(@subpanel.top).to equal(1)
29
+ end
30
+
31
+ it "sets left" do
32
+ expect(@subpanel.left).to equal(2)
33
+ end
34
+
35
+ it "defaults data" do
36
+
37
+ expect(@subpanel.data).to eq({
38
+ :left => '',
39
+ :right => '',
40
+ })
41
+ end
42
+
43
+ it "defaults dividers" do
44
+ expect(@subpanel.dividers).to eq({
45
+ :left => '',
46
+ :right => '',
47
+ })
48
+ end
49
+
50
+ it "calculates content_width" do
51
+ expect(@subpanel.content_width).to equal(80)
52
+ end
53
+ end
54
+
55
+ describe "optional" do
56
+ before do
57
+ @subpanel = Opsicle::Monitor::Subpanel.new(double, 24, 80, 1, 2, {
58
+ :data_l => 'key:',
59
+ :data_r => 'value',
60
+ :divider_l => '<',
61
+ :divider_r => '/>',
62
+ })
63
+ end
64
+
65
+ it "sets data" do
66
+ expect(@subpanel.data).to eq({
67
+ :left => 'key:',
68
+ :right => 'value',
69
+ })
70
+ end
71
+
72
+ it "sets dividers" do
73
+ expect(@subpanel.dividers).to eq({
74
+ :left => '<',
75
+ :right => '/>',
76
+ })
77
+ end
78
+
79
+ it "calculates content_width" do
80
+ expect(@subpanel.content_width).to equal(77)
81
+ end
82
+ end
83
+ end
84
+
85
+ describe "#refresh" do
86
+ describe "strings and dividers" do
87
+ before do
88
+ @window = double
89
+
90
+ @subpanel = Opsicle::Monitor::Subpanel.new(@window, 24, 80, 1, 2, {
91
+ :data_l => 'key:',
92
+ :data_r => 'value',
93
+ :divider_l => '<-',
94
+ :divider_r => '|',
95
+ })
96
+ end
97
+
98
+ describe "when changed" do
99
+ it "sets position" do
100
+ allow(@window).to receive(:addstr)
101
+
102
+ expect(@window).to receive(:setpos).with(1, 2)
103
+
104
+ @subpanel.refresh
105
+ end
106
+
107
+ it "sets data" do
108
+ allow(@window).to receive(:setpos)
109
+
110
+ expect(@window).to receive(:addstr).with("<-key: value|")
111
+
112
+ @subpanel.refresh
113
+ end
114
+
115
+ it "sets truncated data when too long" do
116
+ @subpanel = Opsicle::Monitor::Subpanel.new(@window, 24, 10, 1, 2, {
117
+ :data_l => 'key:',
118
+ :data_r => 'value',
119
+ :divider_l => '<-',
120
+ :divider_r => '|',
121
+ })
122
+
123
+ allow(@window).to receive(:setpos)
124
+
125
+ expect(@window).to receive(:addstr).with("<-key:val|")
126
+
127
+ @subpanel.refresh
128
+ end
129
+ end
130
+
131
+ describe "when unchanged" do
132
+ before do
133
+ allow(@window).to receive(:setpos)
134
+ allow(@window).to receive(:addstr)
135
+
136
+ @subpanel.refresh
137
+ end
138
+
139
+ it "skips position" do
140
+ expect(@window).not_to receive(:setpos)
141
+
142
+ @subpanel.refresh
143
+ end
144
+
145
+ it "skips data" do
146
+ expect(@window).not_to receive(:addstr)
147
+
148
+ @subpanel.refresh
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "lambdas" do
154
+ before do
155
+ @window = double
156
+
157
+ @subpanel = Opsicle::Monitor::Subpanel.new(@window, 24, 80, 0, 0, {
158
+ :data_l => -> { "the answer:" },
159
+ :data_r => -> { "42" }
160
+ })
161
+ end
162
+
163
+ it "sets data when changed" do
164
+ allow(@window).to receive(:setpos)
165
+
166
+ expect(@window).to receive(:addstr).with("the answer: 42")
167
+
168
+ @subpanel.refresh
169
+ end
170
+
171
+ it "sets data when non-string" do
172
+ @subpanel = Opsicle::Monitor::Subpanel.new(@window, 24, 10, 0, 0, {
173
+ :data_l => -> { 2 * 3 * 7 },
174
+ :data_r => -> { 42 }
175
+ })
176
+
177
+ allow(@window).to receive(:setpos)
178
+
179
+ expect(@window).to receive(:addstr).with("42 42")
180
+
181
+ @subpanel.refresh
182
+ end
183
+
184
+ it "sets empty data when nil" do
185
+ @subpanel = Opsicle::Monitor::Subpanel.new(@window, 24, 10, 0, 0, {
186
+ :data_l => -> { nil },
187
+ :data_r => -> { nil }
188
+ })
189
+
190
+ allow(@window).to receive(:setpos)
191
+
192
+ expect(@window).to receive(:addstr).with(" ")
193
+
194
+ @subpanel.refresh
195
+ end
196
+ end
197
+ end
198
+
199
+ end