percheron 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -3
  3. data/Guardfile +5 -0
  4. data/bin/percheron +8 -4
  5. data/lib/percheron.rb +3 -0
  6. data/lib/percheron/actions.rb +15 -0
  7. data/lib/percheron/actions/base.rb +50 -0
  8. data/lib/percheron/actions/build.rb +47 -0
  9. data/lib/percheron/actions/create.rb +109 -0
  10. data/lib/percheron/actions/exec.rb +51 -0
  11. data/lib/percheron/actions/purge.rb +38 -0
  12. data/lib/percheron/actions/recreate.rb +98 -0
  13. data/lib/percheron/actions/rename.rb +64 -0
  14. data/lib/percheron/actions/restart.rb +31 -0
  15. data/lib/percheron/actions/start.rb +46 -0
  16. data/lib/percheron/actions/stop.rb +27 -0
  17. data/lib/percheron/cli.rb +1 -0
  18. data/lib/percheron/cli/abstract_command.rb +7 -0
  19. data/lib/percheron/cli/create_command.rb +3 -2
  20. data/lib/percheron/cli/list_command.rb +2 -8
  21. data/lib/percheron/cli/main_command.rb +1 -0
  22. data/lib/percheron/cli/purge_command.rb +12 -0
  23. data/lib/percheron/cli/recreate_command.rb +9 -2
  24. data/lib/percheron/cli/restart_command.rb +3 -2
  25. data/lib/percheron/cli/start_command.rb +3 -2
  26. data/lib/percheron/cli/stop_command.rb +3 -2
  27. data/lib/percheron/container.rb +120 -5
  28. data/lib/percheron/errors.rb +0 -1
  29. data/lib/percheron/formatters/stack/table.rb +1 -1
  30. data/lib/percheron/null_container.rb +13 -0
  31. data/lib/percheron/oh_dear.rb +46 -0
  32. data/lib/percheron/stack.rb +90 -31
  33. data/lib/percheron/validators/container.rb +9 -1
  34. data/lib/percheron/version.rb +1 -1
  35. data/percheron.gemspec +2 -0
  36. metadata +45 -11
  37. data/lib/percheron/container/actions.rb +0 -15
  38. data/lib/percheron/container/actions/base.rb +0 -21
  39. data/lib/percheron/container/actions/build.rb +0 -58
  40. data/lib/percheron/container/actions/create.rb +0 -56
  41. data/lib/percheron/container/actions/recreate.rb +0 -110
  42. data/lib/percheron/container/actions/start.rb +0 -58
  43. data/lib/percheron/container/actions/stop.rb +0 -33
  44. data/lib/percheron/container/main.rb +0 -193
  45. data/lib/percheron/container/null.rb +0 -15
@@ -4,6 +4,5 @@ module Percheron
4
4
  class StackInvalid < StandardError; end
5
5
  class ContainerInvalid < StandardError; end
6
6
  class ContainerDoesNotExist < StandardError; end
7
- class ContainerNotRunning < StandardError; end
8
7
  end
9
8
  end
@@ -29,7 +29,7 @@ module Percheron
29
29
  end
30
30
 
31
31
  def rows
32
- stack.containers.map do |container_name, container|
32
+ stack.filter_containers.map do |container_name, container|
33
33
  [
34
34
  container_name,
35
35
  container.id,
@@ -0,0 +1,13 @@
1
+ module Percheron
2
+ NullContainer = Naught.build do |config|
3
+ config.mimic Container
4
+
5
+ def info
6
+ {}
7
+ end
8
+
9
+ def kind_of?(klass)
10
+ self.class == klass
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,46 @@
1
+ module Percheron
2
+ class OhDear
3
+
4
+ def initialize(exception)
5
+ @exception = exception
6
+ end
7
+
8
+ def generate
9
+ <<-EOS
10
+
11
+ OH DEAR, we are terribly sorry.. something unexpected occurred :(
12
+
13
+ --snip--
14
+
15
+ Info
16
+ ----
17
+ Ruby: #{RUBY_VERSION}
18
+ Percheron: #{Percheron::VERSION}
19
+
20
+ Trace
21
+ -----
22
+ #{exception_message}
23
+
24
+ #{exception_backtrace}
25
+
26
+ --snip--
27
+
28
+ Please copy the detail between the --snip--'s above and raise a ticket - https://github.com/ashmckenzie/percheron/issues/new?labels=bug
29
+
30
+ EOS
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :exception
36
+
37
+ def exception_message
38
+ exception.inspect
39
+ end
40
+
41
+ def exception_backtrace
42
+ exception.backtrace ? exception.backtrace.join("\n") : ''
43
+ end
44
+
45
+ end
46
+ end
@@ -12,20 +12,17 @@ module Percheron
12
12
  self
13
13
  end
14
14
 
15
- def self.all(config)
16
- all = {}
17
- config.stacks.each do |stack_name, _|
15
+ def self.get(config, stack_name=nil)
16
+ if stack_name
18
17
  stack = new(config, stack_name)
19
- all[stack.name] = stack
20
- end
21
- all
22
- end
23
-
24
- def self.get(config, stack_name)
25
- if stack = all(config)[stack_name]
26
- { stack.name => stack }
18
+ stack ? { stack.name => stack } : {}
27
19
  else
28
- {}
20
+ all = {}
21
+ config.stacks.each do |stack_name, _|
22
+ stack = new(config, stack_name)
23
+ all[stack.name] = stack
24
+ end
25
+ all
29
26
  end
30
27
  end
31
28
 
@@ -33,33 +30,52 @@ module Percheron
33
30
  stack_config.containers.to_hash_by_key(:name)
34
31
  end
35
32
 
36
- def containers
37
- containers = {}
38
- stack_config.containers.each do |container|
39
- container = Container::Main.new(config, self, container.name)
40
- containers[container.name] = container
33
+ # FIXME: YUCK
34
+ def filter_containers(container_names=[])
35
+ container_names = !container_names.empty? ? container_names : filter_container_names
36
+ container_names.inject({}) do |all, container_name|
37
+ all[container_name] = Container.new(config, self, container_name)
38
+ all
41
39
  end
42
- containers
43
40
  end
44
41
 
45
- def stop!
46
- exec_on_containers { |container| container.stop! }
42
+ def stop!(container_names: [])
43
+ container_names = dependant_containers(container_names).reverse
44
+ serial_processor(container_names) { |container| Actions::Stop.new(container).execute! }
47
45
  end
48
46
 
49
- def start!
50
- exec_on_containers { |container| container.start! }
47
+ def start!(container_names: [])
48
+ container_names = dependant_containers(container_names)
49
+ serial_processor(container_names) { |container| Actions::Start.new(container, container.dependant_containers.values).execute! }
51
50
  end
52
51
 
53
- def restart!
54
- exec_on_containers { |container| container.restart! }
52
+ def restart!(container_names: [])
53
+ container_names = dependant_containers(container_names).reverse
54
+ serial_processor(container_names) { |container| Actions::Restart.new(container).execute! }
55
55
  end
56
56
 
57
- def create!
58
- exec_on_containers { |container| container.create! }
57
+ def create!(container_names: [])
58
+ container_names = dependant_containers(container_names)
59
+ serial_processor(container_names) { |container| Actions::Create.new(container).execute! }
59
60
  end
60
61
 
61
- def recreate!(force_recreate: false, force_auto_recreate: false)
62
- exec_on_containers { |container| container.recreate!(force_recreate: force_recreate, force_auto_recreate: force_auto_recreate) }
62
+ def recreate!(container_names: [], force_recreate: false, delete: false)
63
+ current = container_names_final = filter_container_names(container_names)
64
+
65
+ # FIXME: make this suck less
66
+ while true
67
+ current = deps = containers_affected(current).uniq
68
+ break if deps.empty?
69
+ container_names_final += deps
70
+ end
71
+
72
+ serial_processor(container_names_final.uniq) do |container|
73
+ Actions::Recreate.new(container, force_recreate: force_recreate, delete: delete).execute!
74
+ end
75
+ end
76
+
77
+ def purge!
78
+ serial_processor(filter_container_names) { |container| Actions::Purge.new(container).execute! }
63
79
  end
64
80
 
65
81
  def valid?
@@ -71,13 +87,56 @@ module Percheron
71
87
  attr_reader :config, :stack_name
72
88
 
73
89
  def stack_config
74
- @stack_config ||= config.stacks[stack_name] || Hashie::Mash.new({})
90
+ @stack_config ||= (config.stacks[stack_name] || Hashie::Mash.new({}))
75
91
  end
76
92
 
77
- def exec_on_containers
78
- containers.each do |container_name, container|
93
+ def filter_container_names(container_names=[])
94
+ stack_config.containers.map do |container_config|
95
+ if container_names.empty? || container_names.include?(container_config.name)
96
+ container_config.name
97
+ end
98
+ end.compact
99
+ end
100
+
101
+ def exec_on_containers(container_names)
102
+ filter_containers(container_names).each { |_, container| yield(container) }
103
+ end
104
+
105
+ def serial_processor(container_names)
106
+ exec_on_containers(container_names) do |container|
79
107
  yield(container)
108
+ container_names.delete(container.name)
109
+ end
110
+ end
111
+
112
+ def containers_affected(container_names)
113
+ deps = []
114
+ container_names.each do |container_name|
115
+ filter_containers.each do |_, container|
116
+ deps << container.name if container.dependant_container_names.include?(container_name)
117
+ end
118
+ end
119
+ deps
120
+ end
121
+
122
+ def containers_and_their_dependants(container_names)
123
+ all_containers = filter_containers
124
+ container_names.inject({}) do |all, container_name|
125
+ all[container_name] = all_containers[container_name].dependant_container_names
126
+ all
127
+ end
128
+ end
129
+
130
+ def dependant_containers(container_names)
131
+ container_names = filter_container_names(container_names)
132
+
133
+ wip_list = []
134
+ containers_and_their_dependants(container_names).each do |container_name, dependant_container_names|
135
+ wip_list += dependant_container_names unless dependant_container_names.empty?
136
+ wip_list << container_name
80
137
  end
138
+ wip_list.uniq
81
139
  end
140
+
82
141
  end
83
142
  end
@@ -10,7 +10,7 @@ module Percheron
10
10
  message = rules.return { |rule| send(rule) }
11
11
 
12
12
  if message
13
- raise Errors::ContainerInvalid.new(message)
13
+ raise Errors::ContainerInvalid.new(formatted_message(message))
14
14
  else
15
15
  true
16
16
  end
@@ -20,6 +20,14 @@ module Percheron
20
20
 
21
21
  attr_reader :container
22
22
 
23
+ def formatted_message(message)
24
+ if container.name
25
+ "Container config for '%s' is invalid: %s" % [ container.name, message ]
26
+ else
27
+ "Container config is invalid: %s" % [ message ]
28
+ end
29
+ end
30
+
23
31
  def rules
24
32
  [
25
33
  :validate_name,
@@ -1,3 +1,3 @@
1
1
  module Percheron
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
data/percheron.gemspec CHANGED
@@ -25,10 +25,12 @@ Gem::Specification.new do |spec|
25
25
  spec.add_runtime_dependency 'naught', '~> 1.0'
26
26
  spec.add_runtime_dependency 'semantic', '~> 1.4'
27
27
  spec.add_runtime_dependency 'metastore', '~> 0.3'
28
+ spec.add_runtime_dependency 'highline', '~> 1.7.1'
28
29
 
29
30
  spec.add_development_dependency 'bundler', '~> 1.7'
30
31
  spec.add_development_dependency 'rake', '~> 10.0'
31
32
  spec.add_development_dependency 'rspec', '~> 3.0'
33
+ spec.add_development_dependency 'guard-rspec', '~> 4.5'
32
34
  spec.add_development_dependency 'simplecov', '~> 0.9'
33
35
  spec.add_development_dependency 'timecop', '~> 0.7'
34
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: percheron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ash McKenzie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-09 00:00:00.000000000 Z
11
+ date: 2015-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: highline
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.7.1
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.7.1
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: bundler
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +164,20 @@ dependencies:
150
164
  - - "~>"
151
165
  - !ruby/object:Gem::Version
152
166
  version: '3.0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: guard-rspec
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '4.5'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '4.5'
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: simplecov
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -191,18 +219,31 @@ files:
191
219
  - ".travis.yml"
192
220
  - CODE_OF_CONDUCT.md
193
221
  - Gemfile
222
+ - Guardfile
194
223
  - LICENSE.txt
195
224
  - README.md
196
225
  - Rakefile
197
226
  - assets/percheron.png
198
227
  - bin/percheron
199
228
  - lib/percheron.rb
229
+ - lib/percheron/actions.rb
230
+ - lib/percheron/actions/base.rb
231
+ - lib/percheron/actions/build.rb
232
+ - lib/percheron/actions/create.rb
233
+ - lib/percheron/actions/exec.rb
234
+ - lib/percheron/actions/purge.rb
235
+ - lib/percheron/actions/recreate.rb
236
+ - lib/percheron/actions/rename.rb
237
+ - lib/percheron/actions/restart.rb
238
+ - lib/percheron/actions/start.rb
239
+ - lib/percheron/actions/stop.rb
200
240
  - lib/percheron/cli.rb
201
241
  - lib/percheron/cli/abstract_command.rb
202
242
  - lib/percheron/cli/console_command.rb
203
243
  - lib/percheron/cli/create_command.rb
204
244
  - lib/percheron/cli/list_command.rb
205
245
  - lib/percheron/cli/main_command.rb
246
+ - lib/percheron/cli/purge_command.rb
206
247
  - lib/percheron/cli/recreate_command.rb
207
248
  - lib/percheron/cli/restart_command.rb
208
249
  - lib/percheron/cli/start_command.rb
@@ -210,21 +251,14 @@ files:
210
251
  - lib/percheron/config.rb
211
252
  - lib/percheron/config_delegator.rb
212
253
  - lib/percheron/container.rb
213
- - lib/percheron/container/actions.rb
214
- - lib/percheron/container/actions/base.rb
215
- - lib/percheron/container/actions/build.rb
216
- - lib/percheron/container/actions/create.rb
217
- - lib/percheron/container/actions/recreate.rb
218
- - lib/percheron/container/actions/start.rb
219
- - lib/percheron/container/actions/stop.rb
220
- - lib/percheron/container/main.rb
221
- - lib/percheron/container/null.rb
222
254
  - lib/percheron/core_extensions.rb
223
255
  - lib/percheron/docker_connection.rb
224
256
  - lib/percheron/errors.rb
225
257
  - lib/percheron/formatters.rb
226
258
  - lib/percheron/formatters/stack.rb
227
259
  - lib/percheron/formatters/stack/table.rb
260
+ - lib/percheron/null_container.rb
261
+ - lib/percheron/oh_dear.rb
228
262
  - lib/percheron/stack.rb
229
263
  - lib/percheron/validators.rb
230
264
  - lib/percheron/validators/config.rb
@@ -1,15 +0,0 @@
1
- require 'open3'
2
-
3
- require 'percheron/container/actions/base'
4
- require 'percheron/container/actions/stop'
5
- require 'percheron/container/actions/start'
6
- require 'percheron/container/actions/create'
7
- require 'percheron/container/actions/recreate'
8
- require 'percheron/container/actions/build'
9
-
10
- module Percheron
11
- module Container
12
- module Actions
13
- end
14
- end
15
- end
@@ -1,21 +0,0 @@
1
- module Percheron
2
- module Container
3
- module Actions
4
- module Base
5
-
6
- private
7
-
8
- def base_dir
9
- container.dockerfile.dirname.to_s
10
- end
11
-
12
- def in_working_directory(new_dir)
13
- old_dir = Dir.pwd
14
- Dir.chdir(new_dir)
15
- yield
16
- Dir.chdir(old_dir)
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,58 +0,0 @@
1
- module Percheron
2
- module Container
3
- module Actions
4
- class Build
5
-
6
- include Base
7
-
8
- def initialize(container, nocache: false)
9
- @container = container
10
- @nocache = nocache
11
- end
12
-
13
- def execute!
14
- build!
15
- end
16
-
17
- private
18
-
19
- attr_reader :container, :nocache
20
-
21
- def build_opts
22
- {
23
- 'dockerfile' => container.dockerfile.basename.to_s,
24
- 't' => container.image_name,
25
- 'forcerm' => true,
26
- 'nocache' => nocache
27
- }
28
- end
29
-
30
- def build!
31
- in_working_directory(base_dir) do
32
- execute_pre_build_scripts!
33
-
34
- $logger.debug "Building '#{container.image_name}'"
35
- Docker::Image.build_from_dir(base_dir, build_opts) do |out|
36
- $logger.debug '%s' % [ out.strip ]
37
- end
38
- end
39
- end
40
-
41
- def execute_pre_build_scripts!
42
- container.pre_build_scripts.each do |script|
43
- in_working_directory(base_dir) do
44
- command = '/bin/bash -x %s 2>&1' % Pathname.new(File.expand_path(script))
45
- $logger.debug "Executing PRE build '#{command}' for '#{container.name}' container"
46
- Open3.popen2e(command) do |stdin, stdout_err, wait_thr|
47
- while line = stdout_err.gets
48
- $logger.debug line.strip
49
- end
50
- end
51
- end
52
- end
53
- end
54
-
55
- end
56
- end
57
- end
58
- end