percheron 0.5.0 → 0.6.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 (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