docker-app 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/CODE_OF_CONDUCT.md +49 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/bin/console +14 -0
  7. data/bin/setup +8 -0
  8. data/docker-app.gemspec +36 -0
  9. data/exe/docker-app +20 -0
  10. data/lib/docker_app.rb +23 -0
  11. data/lib/docker_app/builder/packer.rb +105 -0
  12. data/lib/docker_app/chef/.chef/knife.rb +118 -0
  13. data/lib/docker_app/chef/chef_build_image.rb +55 -0
  14. data/lib/docker_app/chef/chef_destroy_container.rb +13 -0
  15. data/lib/docker_app/chef/chef_destroy_image.rb +17 -0
  16. data/lib/docker_app/chef/chef_exec_container.rb +16 -0
  17. data/lib/docker_app/chef/chef_run_container.rb +64 -0
  18. data/lib/docker_app/chef/install_container_service.rb +14 -0
  19. data/lib/docker_app/cli.rb +502 -0
  20. data/lib/docker_app/command.rb +16 -0
  21. data/lib/docker_app/config.rb +249 -0
  22. data/lib/docker_app/config/dsl.rb +64 -0
  23. data/lib/docker_app/config/helpers.rb +99 -0
  24. data/lib/docker_app/manager_container.rb +376 -0
  25. data/lib/docker_app/manager_image.rb +119 -0
  26. data/lib/docker_app/manager_swarm.rb +66 -0
  27. data/lib/docker_app/provisioner/base.rb +179 -0
  28. data/lib/docker_app/provisioner/chef.rb +93 -0
  29. data/lib/docker_app/server_settings.rb +361 -0
  30. data/lib/docker_app/version.rb +3 -0
  31. data/lib/templates/example-chef/.chef/knife.rb +5 -0
  32. data/lib/templates/example-chef/config.rb.erb +18 -0
  33. data/lib/templates/example-chef/servers/server1/.chef/knife.rb +8 -0
  34. data/lib/templates/example-chef/servers/server1/config.rb.erb +54 -0
  35. data/lib/templates/example-chef/servers/server1/cookbooks/server1/README.md +1 -0
  36. data/lib/templates/example-chef/servers/server1/cookbooks/server1/metadata.rb.erb +8 -0
  37. data/lib/templates/example-chef/servers/server1/cookbooks/server1/recipes/build.rb +10 -0
  38. data/lib/templates/example-chef/servers/server1/cookbooks/server1/recipes/install.rb +36 -0
  39. data/lib/templates/example-chef/servers/server1/cookbooks/server1/recipes/install_host.rb +9 -0
  40. data/lib/templates/example-chef/servers/server1/cookbooks/server1/templates/index.html.erb +5 -0
  41. data/lib/templates/example-chef/servers/server1/cookbooks/server1/templates/nginx-sites/default.conf.erb +45 -0
  42. data/readme.md +853 -0
  43. data/readme_developers.md +54 -0
  44. metadata +129 -0
@@ -0,0 +1,16 @@
1
+ module DockerApp
2
+ class Command
3
+
4
+ def self.cmd(s)
5
+ puts "running: #{s}"
6
+
7
+ res = nil
8
+ Bundler.with_clean_env do
9
+ res = `#{s}`
10
+ end
11
+
12
+ puts "#{res}"
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,249 @@
1
+ # encoding: utf-8
2
+ require 'docker_app/config/dsl'
3
+ require 'docker_app/config/helpers'
4
+
5
+
6
+
7
+ module DockerApp
8
+ module Config
9
+ #class Error < DockerApp::Error; end
10
+
11
+ DEFAULTS = {
12
+ :config_file => 'config.rb',
13
+ :tmp_path => 'temp'
14
+ }
15
+
16
+ class << self
17
+ #include Utilities::Helpers
18
+
19
+ attr_reader :servers, :options,
20
+ :root_path, :config_file, :tmp_path
21
+
22
+
23
+ # Define on self, since it's a class method
24
+ def method_missing(method_sym, *arguments, &block)
25
+ # the first argument is a Symbol, so you need to_s it if you want to pattern match
26
+ if options.has_key?(method_sym)
27
+ return options[method_sym]
28
+ else
29
+ super
30
+ end
31
+ #if method_sym.to_s =~ /^find_by_(.*)$/
32
+ # find($1.to_sym => arguments.first)
33
+
34
+ end
35
+
36
+
37
+
38
+ # Loads the user's +config.rb+ and all model files.
39
+ def load(opts = {})
40
+ update(opts) # from the command line
41
+
42
+ #config_file = 'temp_config.rb'
43
+
44
+ puts "config file: #{config_file}"
45
+
46
+ unless File.exist?(config_file)
47
+ #raise Error, "Could not find configuration file: '#{config_file}'."
48
+ raise "Could not find configuration file: '#{config_file}'."
49
+ end
50
+
51
+ text_config = File.read(config_file)
52
+
53
+ dsl = DSL.new
54
+ dsl.instance_eval(text_config, config_file)
55
+
56
+ # set options from dsl object
57
+ update(dsl._config_options) # from config.rb
58
+ # command line takes precedence
59
+ update(opts)
60
+
61
+ #Dir[File.join(File.dirname(config_file), 'models', '*.rb')].each do |model|
62
+ # dsl.instance_eval(File.read(model), model)
63
+ #end
64
+
65
+ # servers
66
+ # Identify all servers
67
+ if @options['server']
68
+ srv_name = @options['server'] || @options[:server]
69
+ # one server
70
+ @servers = {srv_name => dsl._config_servers[srv_name]}
71
+ else
72
+ # all servers
73
+ @servers = dsl._config_servers
74
+ end
75
+
76
+
77
+ @servers.each do |name, sc|
78
+ # from common config
79
+ sc.common_config = self
80
+ sc.properties['name'] ||= name
81
+ #sc.properties['common'] = Config.options[:common]
82
+ end
83
+
84
+
85
+
86
+ end
87
+
88
+
89
+ def dir_gem_root
90
+ return @dir_gem_root unless @dir_gem_root.nil?
91
+
92
+ #
93
+ spec = Gem::Specification.find_by_name("docker-app")
94
+ @dir_gem_root = spec.gem_dir
95
+
96
+ @dir_gem_root
97
+ end
98
+
99
+ def options
100
+ return @options unless @options.nil?
101
+
102
+ @options = {}
103
+ @options
104
+ end
105
+
106
+ #def servers
107
+ #options[:servers]
108
+ #@_servers || []
109
+ #end
110
+
111
+
112
+ ### NOT USED
113
+ ## TODO: refactor
114
+ def self.load_settings_for_server(name, opts={})
115
+ settings = ServerSettings.new
116
+
117
+ settings.set 'name', name
118
+
119
+ # set from main Config
120
+ Config.servers[name].each do |k,v|
121
+ settings.properties[k]=v
122
+ end
123
+
124
+
125
+ #puts "current=#{File.dirname(__FILE__)}"
126
+ #puts "ff=#{file_base_settings}"
127
+
128
+ #
129
+ #t = File.read(file_base_settings) rescue ''
130
+ #eval(t, settings.get_binding)
131
+
132
+
133
+ #
134
+ f = file_settings_for_server(name)
135
+ t = File.read(f) rescue ''
136
+ eval(t, settings.get_binding)
137
+
138
+ #
139
+ settings.properties['name'] ||= name
140
+
141
+ # from common config
142
+ settings.properties['common'] = Config.options[:common]
143
+
144
+ settings
145
+ end
146
+
147
+
148
+ ### helpers
149
+
150
+ def self.file_settings_for_server(name)
151
+ #File.join(File.dirname(__FILE__), '..', 'config', "#{name}.rb")
152
+ File.join(Config.root_path, 'servers', name, 'config.rb')
153
+ end
154
+
155
+ def self.file_server_base_settings
156
+ File.join(File.dirname(__FILE__), '..', 'config' ,'common.rb')
157
+ end
158
+
159
+
160
+ private
161
+
162
+ # If :root_path is set in the options, all paths will be updated.
163
+ # Otherwise, only the paths given will be updated.
164
+ def update(opts = {})
165
+ #puts "update. opts=#{opts}"
166
+
167
+ # root_path
168
+ root_path = opts[:root_path].to_s.strip
169
+
170
+ #puts "root from opts = #{root_path}"
171
+
172
+ if root_path.empty?
173
+ root_path = File.path(Dir.getwd)
174
+ end
175
+
176
+ new_root = root_path.empty? ? false : set_root_path(root_path)
177
+
178
+ DEFAULTS.each do |name, ending|
179
+ set_path_variable(name, options[name], ending, new_root)
180
+ end
181
+
182
+ # options
183
+ opts.each do |name, v|
184
+ set_variable(name, v)
185
+ end
186
+
187
+ # config file
188
+ set_path_variable("config_file", options['config_file'], DEFAULTS['config_file'], new_root)
189
+
190
+ end
191
+
192
+ # Sets the @root_path to the given +path+ and returns it.
193
+ # Raises an error if the given +path+ does not exist.
194
+ def set_root_path(path)
195
+ # allows #reset! to set the default @root_path,
196
+ # then use #update to set all other paths,
197
+ # without requiring that @root_path exist.
198
+ return @root_path if path == @root_path
199
+
200
+ path = File.expand_path(path)
201
+
202
+ unless File.directory?(path)
203
+ raise Error, <<-EOS
204
+ Root Path Not Found
205
+ When specifying a --root-path, the path must exist.
206
+ Path was: #{ path }
207
+ EOS
208
+ end
209
+ @root_path = path
210
+ end
211
+
212
+
213
+
214
+ def set_variable(name, v)
215
+ #instance_variable_set(:"@#{name}", v) if v
216
+ options[name] = v
217
+ end
218
+
219
+ def set_path_variable(name, path, ending, root_path)
220
+ # strip any trailing '/' in case the user supplied this as part of
221
+ # an absolute path, so we can match it against File.expand_path()
222
+ path = path.to_s.sub(/\/\s*$/, '').lstrip
223
+ new_path = false
224
+ # If no path is given, the variable will not be set/updated
225
+ # unless a root_path was given. In which case the value will
226
+ # be updated with our default ending.
227
+ if path.empty?
228
+ new_path = File.join(root_path, ending) if root_path
229
+ else
230
+ # When a path is given, the variable will be set/updated.
231
+ # If the path is relative, it will be joined with root_path (if given),
232
+ # or expanded relative to PWD.
233
+ new_path = File.expand_path(path)
234
+ unless path == new_path
235
+ new_path = File.join(root_path, path) if root_path
236
+ end
237
+ end
238
+ instance_variable_set(:"@#{name}", new_path) if new_path
239
+ end
240
+
241
+ #def reset!
242
+ # @root_path = File.join(File.expand_path(ENV['HOME'] || ''), 'DockerApp')
243
+ # update(:root_path => @root_path)
244
+ #end
245
+ end
246
+
247
+ #reset! # set defaults on load
248
+ end
249
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ module DockerApp
4
+ module Config
5
+ # Context for loading user config.rb and model files.
6
+ class DSL
7
+ #class Error < Backup::Error; end
8
+ #Server = DockerApp::Server
9
+
10
+ attr_reader :_config_options
11
+ attr_reader :_config_servers
12
+
13
+ def initialize
14
+ @_config_options = {}
15
+ @_config_servers = {}
16
+ end
17
+
18
+ # Allow users to set command line path options in config.rb
19
+ [:root_path, :tmp_path].each do |name|
20
+ define_method name, lambda {|path| _config_options[name] = path }
21
+ end
22
+
23
+ # options - common
24
+ [
25
+ :prefix, :image_prefix, :container_prefix, :service_prefix,
26
+ :dir_data
27
+ ].each do |name|
28
+ define_method name, lambda {|path| _config_options[name] = path }
29
+ end
30
+
31
+ # allowed options
32
+ [:common, :base].each do |name|
33
+ define_method name, lambda {|v| _config_options[name] = v }
34
+ end
35
+
36
+
37
+ def server(server_name, &block)
38
+ sc = ServerSettings.new
39
+ block.call(sc)
40
+ #sc.instance_eval(&block)
41
+ _config_servers[server_name] = sc
42
+ end
43
+
44
+ # Allows users to create preconfigured models.
45
+ =begin
46
+ def preconfigure(name, &block)
47
+ unless name.is_a?(String) && name =~ /^[A-Z]/
48
+ raise Error, "Preconfigured model names must be given as a string " +
49
+ "and start with a capital letter."
50
+ end
51
+
52
+ if DSL.const_defined?(name)
53
+ raise Error, "'#{ name }' is already in use " +
54
+ "and can not be used for a preconfigured model."
55
+ end
56
+
57
+ DSL.const_set(name, Class.new(Model))
58
+ DSL.const_get(name).preconfigure(&block)
59
+ end
60
+ =end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,99 @@
1
+ # encoding: utf-8
2
+ require 'ostruct'
3
+
4
+ module DockerApp
5
+ module Config
6
+ module Helpers
7
+
8
+ def self.included(klass)
9
+ klass.extend ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ def defaults
15
+ @defaults ||= Config::Defaults.new
16
+
17
+ if block_given?
18
+ yield @defaults
19
+ else
20
+ @defaults
21
+ end
22
+ end
23
+
24
+ # Used only within the specs
25
+ def clear_defaults!
26
+ defaults.reset!
27
+ end
28
+
29
+ def deprecations
30
+ @deprecations ||= {}
31
+ end
32
+
33
+ protected
34
+
35
+
36
+
37
+ end # ClassMethods
38
+
39
+ private
40
+
41
+ ##
42
+ # Sets any pre-configured default values.
43
+ # If a default value was set for an invalid accessor,
44
+ # this will raise a NameError.
45
+ def load_defaults!
46
+ self.class.defaults._attributes.each do |name|
47
+ val = self.class.defaults.send(name)
48
+ val = val.dup rescue val
49
+ send(:"#{ name }=", val)
50
+ end
51
+ end
52
+
53
+ ##
54
+ # Check missing methods for deprecated attribute accessors.
55
+ #
56
+ # If a value is set on an accessor that has been deprecated
57
+ # using #attr_deprecate, a warning will be issued and any
58
+ # :action (Proc) specified will be called with a reference to
59
+ # the class instance and the value set on the deprecated accessor.
60
+ # See #attr_deprecate and #log_deprecation_warning
61
+ #
62
+ # Note that OpenStruct (used for setting defaults) does not allow
63
+ # multiple arguments when assigning values for members.
64
+ # So, we won't allow it here either, even though an attr_accessor
65
+ # will accept and convert them into an Array. Therefore, setting
66
+ # an option value using multiple values, whether as a default or
67
+ # directly on the class' accessor, should not be supported.
68
+ # i.e. if an option will accept being set as an Array, then it
69
+ # should be explicitly set as such. e.g. option = [val1, val2]
70
+ #
71
+ def method_missing(name, *args)
72
+ if method = name.to_s.chomp!('=')
73
+ if (len = args.count) != 1
74
+ raise ArgumentError,
75
+ "wrong number of arguments (#{ len } for 1)", caller(1)
76
+ end
77
+ end
78
+
79
+ super
80
+ end
81
+
82
+ end # Helpers
83
+
84
+ # Store for pre-configured defaults.
85
+ class Defaults < OpenStruct
86
+ # Returns an Array of all attribute method names
87
+ # that default values were set for.
88
+ def _attributes
89
+ @table.keys
90
+ end
91
+
92
+ # Used only within the specs
93
+ def reset!
94
+ @table.clear
95
+ end
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,376 @@
1
+ module DockerApp
2
+ class ManagerContainer
3
+
4
+ def self.save_chef_config(settings)
5
+ require 'json'
6
+ filename = settings.filename_chef_config
7
+ FileUtils.mkdir_p(File.dirname(filename))
8
+ File.open(filename,"w+") do |f|
9
+ f.write(settings.all_attributes.to_json)
10
+ end
11
+
12
+ true
13
+ end
14
+
15
+
16
+ def self.save_config_json(settings)
17
+ require 'json'
18
+ filename = settings.filename_config_json
19
+ FileUtils.mkdir_p(File.dirname(filename))
20
+ File.open(filename,"w+") do |f|
21
+ f.write(settings.all_attributes.to_json)
22
+ end
23
+
24
+ true
25
+ end
26
+
27
+
28
+
29
+
30
+ ### run
31
+
32
+ def self.run_container(server_name, settings={})
33
+ puts "creating and running container.."
34
+ #settings = load_settings(server_name)
35
+
36
+ # generate config
37
+ save_config_json(settings)
38
+
39
+
40
+ # destroy
41
+ destroy_container(server_name, settings)
42
+
43
+ # create
44
+ create_container(settings)
45
+
46
+
47
+ # START && run provision after start
48
+ start_container(name, settings)
49
+
50
+
51
+ # TODO: systemd service
52
+ #res_service = _install_service_container(settings)
53
+
54
+
55
+ true
56
+ end
57
+
58
+ def self.create_container(settings)
59
+ # create
60
+ net_options = ""
61
+ networks = settings['docker'].fetch('network', {}).fetch('networks', [])
62
+ if networks && networks[0]
63
+ network = networks[0]
64
+ #puts "network=#{network}"
65
+ net_options << "--net #{network['net']} "
66
+ net_options << "--ip #{network['ip']} " if network['ip']
67
+ net_options << "--mac-address #{network['mac_address']} " if network['mac_address']
68
+ end
69
+
70
+
71
+ cmd %Q(docker create --name #{settings.container_name} #{net_options} #{settings.docker_ports_string} #{settings.docker_volumes_string} #{settings.docker_volumes_from_string} #{settings.docker_links_string} #{settings.run_extra_options_string} #{settings.run_env_variables_string} #{settings.image_name} #{settings['docker']['command']} #{settings['docker']['run_options']})
72
+
73
+ # network
74
+ setup_network(settings)
75
+ end
76
+
77
+
78
+ def self.setup_network(settings)
79
+ container_name = settings.container_name
80
+
81
+ # networks
82
+ networks = settings['docker'].fetch('network', {}).fetch('networks', [])
83
+ if networks
84
+ ind = 0
85
+ networks.each do |net|
86
+ ind = ind + 1
87
+
88
+ #
89
+ next if net['action']=='remove'
90
+
91
+ # skip first network
92
+ next if ind==1
93
+
94
+ # connect
95
+ ip = net['ip']
96
+ s_ip = "--ip #{ip}" if ip
97
+ #puts %Q(docker network connect #{s_ip} #{net['net']} #{settings.container_name})
98
+ cmd %Q(docker network connect #{s_ip} #{net['net']} #{settings.container_name})
99
+ end
100
+
101
+ # remove
102
+ networks.each do |net|
103
+ next unless net['action']=='remove'
104
+ cmd %Q(docker network disconnect #{net['net']} #{settings.container_name})
105
+ end
106
+ end
107
+ end
108
+
109
+
110
+
111
+
112
+ def self.start_container(name, settings)
113
+ ### BEFORE START
114
+ # run setup provision scripts
115
+ DockerApp::Provisioner::Base.run_provision_scripts_setup(settings)
116
+
117
+
118
+ ### start
119
+ cmd %Q(docker start #{settings.container_name})
120
+
121
+ # wait
122
+ wait_until_running(settings.container_name)
123
+
124
+ ### AFTER START
125
+
126
+ # setup
127
+ setup_container_after_start(settings)
128
+
129
+ # provision after start
130
+ # run bootstrap provision scripts
131
+ DockerApp::Provisioner::Base.run_provision_scripts_bootstrap(settings)
132
+
133
+ end
134
+
135
+
136
+ def self.wait_until_running(container_name)
137
+ retries = 10
138
+ until system("docker exec #{container_name} true") || retries < 0
139
+ sleep 1
140
+ retries = retries - 1
141
+ end
142
+
143
+ assert_container_running(container_name)
144
+ end
145
+
146
+ def self.assert_container_running(container_name)
147
+ res = system("docker exec #{container_name} true")
148
+ assert res, "Container #{container_name} is not running"
149
+ end
150
+
151
+
152
+ =begin
153
+ def self._prepare_provision_before_start_chef(settings, script)
154
+ puts "_prepare_provision_before_start_chef"
155
+
156
+ require_relative '../../lib/docker_app/provisioner/provisioner_chef'
157
+
158
+ provisioner = DockerApp::Provisioner::Chef.new(settings)
159
+ provisioner.copy_config_file
160
+
161
+ end
162
+ =end
163
+
164
+ def self.setup_container_after_start(settings)
165
+
166
+ # default gateway
167
+ network = settings['docker']['network']
168
+ if network
169
+ gateway = network['default_gateway']
170
+
171
+ if gateway
172
+ # fix default gateway
173
+ #cmd %Q(docker exec #{settings.container_name} ip route change default via #{gateway} dev eth1)
174
+ cmd %Q(docker exec #{settings.container_name} ip route change default via #{gateway})
175
+ end
176
+ end
177
+
178
+
179
+
180
+ # fix hosts
181
+ container_hosts = settings['docker']['hosts'] || []
182
+ container_hosts.each do |r|
183
+ #cmd %Q(docker exec #{settings.container_name} bash -c 'echo "#{r[0]} #{r[1]}" >> /etc/hosts')
184
+ cmd %Q(docker exec #{settings.container_name} sh -c 'echo "#{r[0]} #{r[1]}" >> /etc/hosts')
185
+ end
186
+ end
187
+
188
+
189
+
190
+
191
+
192
+
193
+ ### systemd service
194
+
195
+ def self._install_service_container(settings)
196
+ # not work
197
+ #cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} install_container_service.rb )
198
+
199
+ # work
200
+ #cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} -j config_run_install_container_service.json )
201
+
202
+ # work
203
+ #cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} --override-runlist 'recipe[server-api::install_container_service]' )
204
+
205
+ #
206
+ cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} -j config/config-#{settings.name}.json --override-runlist 'recipe[server-api::install_container_service]' )
207
+ end
208
+
209
+
210
+ def self._remove_service_container(settings)
211
+ cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} -j config/config-#{settings.name}.json --override-runlist 'recipe[server-api::remove_container_service]' )
212
+ end
213
+
214
+
215
+
216
+ =begin
217
+ def self._run_container_chef(settings)
218
+ # generate json config for chef
219
+ save_chef_config(settings)
220
+
221
+ # run chef
222
+ #s_run = %Q(cd #{settings.name} && chef-client -z -j config.json -c ../.chef/knife.rb -N #{settings.name} ../lib/chef_container_run.rb)
223
+
224
+ # good - 2016-nov-19
225
+ #cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} chef_run_container.rb)
226
+
227
+ #
228
+ res_chef = run_chef_recipe(settings, 'chef_run_container.rb')
229
+
230
+ res_chef
231
+ end
232
+
233
+ =end
234
+
235
+
236
+
237
+
238
+ ###
239
+
240
+ def self.destroy_container(server_name, settings)
241
+ puts "destroying container #{server_name}..."
242
+
243
+ # TODO: stop, remove systemd service
244
+ #res_service = _remove_service_container(settings)
245
+
246
+ #
247
+ cmd %Q(docker rm -f #{settings.container_name} )
248
+
249
+
250
+
251
+ # if chef
252
+ if settings['build']['build_type']=='chef'
253
+ return destroy_container_chef(settings)
254
+ end
255
+
256
+ #
257
+ return true
258
+ end
259
+
260
+
261
+ def self.destroy_container_chef(settings)
262
+ # destroy temp container
263
+ cmd %Q(docker rm -f chef-converge.#{settings.image_name} )
264
+
265
+ #
266
+ res_chef = run_chef_recipe(settings, 'chef_destroy_container.rb')
267
+ #cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} chef_destroy_container.rb)
268
+
269
+ #
270
+ chef_remove_data(settings)
271
+
272
+ end
273
+
274
+
275
+
276
+
277
+ ### stop container
278
+
279
+ def self.stop_container(server_name, settings)
280
+ puts "stopping container #{server_name}..."
281
+
282
+ #
283
+ cmd %Q(docker stop #{settings.container_name} )
284
+
285
+ #
286
+ return true
287
+ end
288
+
289
+
290
+ ### run task on running container
291
+ def self.exec_task(server_name, recipe_name)
292
+ #raise 'not implemented'
293
+
294
+ settings = load_settings(server_name)
295
+
296
+ # check script exists
297
+ script_path = "#{settings.name}/cookbooks/#{settings.name}/recipes/#{recipe_name}.rb"
298
+ f = File.expand_path('.', script_path)
299
+
300
+ if !File.exists?(f)
301
+ puts "script not found: #{f}. Skipping"
302
+ return false
303
+ end
304
+
305
+ #
306
+ cmd %Q(SERVER_NAME=#{settings.name} chef-client -z --override-runlist 'recipe[server-api::exec_container]' )
307
+ #cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} --override-runlist 'recipe[#{settings.name}::#{recipe_name}]' )
308
+ #cmd %Q(SERVER_NAME=#{settings.name} chef-client -z -N #{settings.name} chef_exec_container.rb )
309
+
310
+ return true
311
+ end
312
+
313
+
314
+ ###
315
+ def self.clear_cache(name, settings)
316
+ # common cache
317
+ cmd("rm -rf ~/.chef/cache")
318
+ cmd("rm -rf ~/.chef/local-mode-cache")
319
+
320
+ # cache for server
321
+ cmd("rm -rf #{settings.dir_server_root}/.chef/local-mode-cache")
322
+ #cmd("rm -rf ~/.chef/package-cache")
323
+
324
+ # cache in gem
325
+ cmd("rm -rf #{Config.dir_gem_root}/lib/docker_app/.chef/local-mode-cache")
326
+
327
+
328
+ end
329
+
330
+ ###
331
+
332
+ def self.cmd(s)
333
+ Command.cmd(s)
334
+ end
335
+
336
+
337
+
338
+ ### helpers - chef
339
+
340
+ def self.run_chef_recipe(settings, recipe_rb)
341
+ cmd %Q(cd #{Config.root_path} && SERVER_NAME=#{settings.name} SERVER_PATH=#{settings.dir_server_root} chef exec chef-client -z -N #{settings.container_name} -j #{settings.filename_config_json} -c #{chef_config_knife_path} #{chef_recipe_path(recipe_rb)} )
342
+ end
343
+
344
+ def self.run_chef_recipe_server_recipe(settings, server_recipe)
345
+ cmd %Q(cd #{Config.root_path} && SERVER_NAME=#{settings.name} SERVER_PATH=#{settings.dir_server_root} chef exec chef-client -z -N #{settings.container_name} -c #{chef_config_knife_path} --override-runlist 'recipe[#{settings.name}::#{server_recipe}]' )
346
+ end
347
+
348
+
349
+ def self.chef_config_knife_path
350
+ "#{Config.dir_gem_root}/lib/docker_app/chef/.chef/knife.rb"
351
+ end
352
+
353
+ def self.chef_recipe_path(p)
354
+ "#{Config.dir_gem_root}/lib/docker_app/chef/#{p}"
355
+ end
356
+
357
+
358
+ def self.chef_remove_data(settings)
359
+ #
360
+ cmd %Q(cd #{Config.root_path} && chef exec knife node delete #{settings.chef_node_name} -y -c #{chef_config_knife_path})
361
+
362
+ # clean chef client, node
363
+ cmd %Q(cd #{Config.root_path} && rm -f #{settings.filename_chef_node_json} )
364
+ cmd %Q(cd #{Config.root_path} && rm -f #{settings.filename_chef_client_json} )
365
+ end
366
+
367
+
368
+ ### common helpers
369
+ def self.assert(expression, string = "Assert failed")
370
+ unless expression
371
+ throw Exception.new string
372
+ end
373
+ end
374
+
375
+ end
376
+ end