luban 0.3.3 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +16 -1
  4. data/lib/luban/deployment/cli/application/base.rb +34 -15
  5. data/lib/luban/deployment/cli/application/builder.rb +2 -2
  6. data/lib/luban/deployment/cli/application/publisher.rb +15 -4
  7. data/lib/luban/deployment/cli/application/scm/rsync.rb +1 -1
  8. data/lib/luban/deployment/cli/command.rb +28 -21
  9. data/lib/luban/deployment/cli/package/{binary.rb → base.rb} +6 -7
  10. data/lib/luban/deployment/cli/package/installer/core.rb +1 -1
  11. data/lib/luban/deployment/cli/package/installer/paths.rb +0 -8
  12. data/lib/luban/deployment/cli/package/installer.rb +8 -0
  13. data/lib/luban/deployment/cli/package/worker.rb +14 -0
  14. data/lib/luban/deployment/cli/package.rb +1 -2
  15. data/lib/luban/deployment/cli/project.rb +17 -3
  16. data/lib/luban/deployment/cli/service/base.rb +49 -0
  17. data/lib/luban/deployment/cli/service/configurator.rb +57 -0
  18. data/lib/luban/deployment/cli/service/controller.rb +99 -0
  19. data/lib/luban/deployment/cli/service/installer.rb +9 -0
  20. data/lib/luban/deployment/cli/service/worker.rb +37 -0
  21. data/lib/luban/deployment/cli/service.rb +5 -0
  22. data/lib/luban/deployment/cli.rb +1 -0
  23. data/lib/luban/deployment/helpers/configuration.rb +40 -9
  24. data/lib/luban/deployment/helpers/utils.rb +2 -2
  25. data/lib/luban/deployment/packages/bundler.rb +2 -4
  26. data/lib/luban/deployment/packages/git.rb +2 -4
  27. data/lib/luban/deployment/packages/openssl.rb +2 -4
  28. data/lib/luban/deployment/packages/ruby.rb +2 -4
  29. data/lib/luban/deployment/packages/rubygems.rb +5 -7
  30. data/lib/luban/deployment/packages/yaml.rb +1 -1
  31. data/lib/luban/deployment/parameters.rb +2 -0
  32. data/lib/luban/deployment/version.rb +1 -1
  33. data/lib/luban/deployment/worker/base.rb +1 -1
  34. data/lib/luban/deployment/worker/paths.rb +50 -0
  35. metadata +10 -5
  36. data/lib/luban/deployment/cli/package/service.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d711bbdde3319889d6851b02c652b1420f98fba5
4
- data.tar.gz: 6d91b1ab03f54730ad59255d25ef8a659d811029
3
+ metadata.gz: 77cb6b05848cfa60305de26ee0962a064a001f68
4
+ data.tar.gz: 375494b42b12ca2a917b2432bbac689b979d64d3
5
5
  SHA512:
6
- metadata.gz: 3eb285d74e5c6a5cec47efb0130bebca1fc744b47815636f7bf8bdd25c1b2a71df745fd15db3d401b83954e7a45c3c18e9749fe7745b71a9b3da0fcb10c7b820
7
- data.tar.gz: a2882bac46666c2cbd9c86a204cb507789de5870f8c7b1a6bbab2953565b5a6c4e86af0be88e08c22afa7386bb8bacc5d365a3e5c93984bd3c8e0c5a8eb3bc9c
6
+ metadata.gz: 7ae1e7277dcd129b2f2ad2e21b46fdcd9779820aa9077506a61df285404cc7b0b781ae751b0a63f08aa99586de50b480f7b01ec1e20e4fce01c60d4a8fdb495c
7
+ data.tar.gz: 64600972a5b28ccefc5dcc4423f7262b35e0b274d9341bd280accd80f83dd72f10adbd6070c7631fa6aa75a006b7b411d2544d04ead9fc179a6a4395a7985905
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .DS_Store
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Change log
2
2
 
3
+ ## Version 0.3.5 (May 06, 2016)
4
+
5
+ New features:
6
+ * Created Luban::Deployment::Service::Base to handle service package deployment
7
+ * Added logrotate support
8
+ * Generated profile locally before publishing to remote servers for a given service package
9
+
10
+ Minor enhancements:
11
+ * Renamed Luban::Deployment::Package::Binary to Luban::Deployment::Package::Base for clarity
12
+ * Added convenient class method #default_executable to define executable method for a given package
13
+ * Minor code refactoring and cleanup
14
+
15
+ Bug fixes:
16
+ * Fixed a bug in md5 calculation on a given folder
17
+
3
18
  ## Version 0.3.3 (Apr 18, 2016)
4
19
 
5
20
  Bug fixes:
@@ -19,7 +34,7 @@ Bug fixes:
19
34
  ## Version 0.3.1 (Apr 13, 2016)
20
35
 
21
36
  Minor enhancements:
22
- * Add SSH auth method "password" in addition to "keyboard-interactive"
37
+ * Added SSH auth method "password" in addition to "keyboard-interactive"
23
38
  * Removed support for production stages
24
39
 
25
40
  Bug fixes:
@@ -40,7 +40,7 @@ module Luban
40
40
  command(name, base: Luban::Deployment::Package::Base.package_class(name))
41
41
  end
42
42
  pkg.update_package_options(version, opts)
43
- services[name] = pkg if pkg.is_a?(Luban::Deployment::Package::Service)
43
+ services[name] = pkg if pkg.is_a?(Luban::Deployment::Service::Base)
44
44
  packages[name] = pkg
45
45
  end
46
46
  alias_method :require_package, :package
@@ -84,7 +84,8 @@ module Luban
84
84
  end
85
85
  end
86
86
 
87
- %i(cleanup binstubs show_current show_summary which whence).each do |action|
87
+ (Luban::Deployment::Command::Tasks::Install::Actions -
88
+ %i(setup build destroy)).each do |action|
88
89
  define_method(action) do |args:, opts:|
89
90
  show_app_environment
90
91
  packages.each_value { |p| p.send(__method__, args: args, opts: opts) }
@@ -104,7 +105,15 @@ module Luban
104
105
 
105
106
  def deploy(args:, opts:)
106
107
  show_app_environment
107
- deploy_releases(args: args, opts: opts)
108
+ deploy_profile(args: args, opts: opts) if has_profile?
109
+ deploy_release(args: args, opts: opts) if has_source?
110
+ end
111
+
112
+ Luban::Deployment::Command::Tasks::Control::Actions.each do |action|
113
+ define_method(action) do |args:, opts:|
114
+ show_app_environment
115
+ services.each_value { |s| s.send(__method__, args: args, opts: opts) }
116
+ end
108
117
  end
109
118
 
110
119
  protected
@@ -133,8 +142,9 @@ module Luban
133
142
  end
134
143
 
135
144
  def set_default_profile
136
- profile_path = config_finder[:application].stage_config_path.join('profile')
137
- profile(profile_path, scm: :rsync) if profile_path.directory?
145
+ if config_finder[:application].has_profile?
146
+ profile(config_finder[:application].stage_profile_path, scm: :rsync)
147
+ end
138
148
  end
139
149
 
140
150
  def load_configuration
@@ -151,8 +161,8 @@ module Luban
151
161
  puts "#{display_name} in #{parent.class.name}"
152
162
  end
153
163
 
154
- %i(build destroy cleanup).each do |m|
155
- define_task_method("#{m}!", task: m, worker: :builder)
164
+ %i(build destroy cleanup).each do |task|
165
+ dispatch_task "#{task}!", to: :builder, as: task
156
166
  end
157
167
 
158
168
  def build_repositories(args:, opts:)
@@ -160,24 +170,33 @@ module Luban
160
170
  build_repository!(args: args, opts: opts.merge(repository: source)) if has_source?
161
171
  end
162
172
 
163
- def deploy_releases(args:, opts:)
164
- deploy_release(args: args, opts: opts.merge(repository: profile)) if has_profile?
165
- deploy_release(args: args, opts: opts.merge(repository: source)) if has_source?
173
+ def deploy_profile(args:, opts:)
174
+ update_profile!(args: args, opts: opts)
175
+ deploy_profile!(args: args, opts: opts.merge(repository: profile))
176
+ end
177
+
178
+ def update_profile!(args:, opts:)
179
+ services.each_value { |s| s.send(:update_profile, args: args, opts: opts) }
166
180
  end
167
181
 
168
182
  def deploy_release(args:, opts:)
183
+ deploy_release!(args: args, opts: opts.merge(repository: source))
184
+ end
185
+
186
+ def deploy_release!(args:, opts:)
169
187
  package_release!(args: args, opts: opts)[:release].tap do |release|
170
188
  unless release.nil?
171
189
  publish_release!(args: args, opts: opts.merge(release: release))
172
190
  end
173
191
  end
174
192
  end
193
+ alias_method :deploy_profile!, :deploy_release!
175
194
 
176
- define_task_method("promptless_authen!", task: :promptless_authen, worker: :authenticator)
177
- define_task_method("public_key!", task: :public_key, worker: :authenticator, locally: true)
178
- define_task_method("build_repository!", task: :build, worker: :repository, locally: true)
179
- define_task_method("package_release!", task: :package, worker: :repository, locally: true)
180
- define_task_method("publish_release!", task: :publish, worker: :publisher)
195
+ dispatch_task :promptless_authen!, to: :authenticator, as: :promptless_authen
196
+ dispatch_task :public_key!, to: :authenticator, as: :public_key, locally: true
197
+ dispatch_task :build_repository!, to: :repository, as: :build, locally: true
198
+ dispatch_task :package_release!, to: :repository, as: :package, locally: true
199
+ dispatch_task :publish_release!, to: :publisher, as: :publish
181
200
  end
182
201
  end
183
202
  end
@@ -41,8 +41,8 @@ module Luban
41
41
  protected
42
42
 
43
43
  def bootstrap
44
- assure_dirs(etc_path, tmp_path, downloads_path,
45
- app_bin_path, app_tmp_path,
44
+ assure_dirs(logrotate_path, downloads_path,
45
+ tmp_path, app_bin_path, app_tmp_path,
46
46
  releases_path, shared_path)
47
47
  assure_linked_dirs
48
48
  end
@@ -120,18 +120,18 @@ module Luban
120
120
 
121
121
  def create_symlinks
122
122
  send("create_#{release_name}_symlinks")
123
+ create_shared_symlinks_for(:directory, linked_dirs)
124
+ create_shared_symlinks_for(:directory, bundle_linked_dirs) if file?(gemfile)
123
125
  end
124
126
 
125
127
  def create_profile_symlinks
126
128
  create_release_symlink(shared_path)
127
- create_shared_symlinks_for(:directory, linked_dirs)
128
- create_shared_symlinks_for(:directory, bundle_linked_dirs) if file?(gemfile)
129
+ create_etc_symlinks
129
130
  end
130
131
 
131
132
  def create_app_symlinks
132
133
  create_release_symlink(app_path)
133
- create_shared_symlinks_for(:directory, linked_dirs | %w(profile))
134
- create_shared_symlinks_for(:directory, bundle_linked_dirs) if file?(gemfile)
134
+ create_shared_symlinks_for(:directory, %w(profile))
135
135
  create_shared_symlinks_for(:file, linked_files)
136
136
  end
137
137
 
@@ -148,6 +148,17 @@ module Luban
148
148
  end
149
149
  end
150
150
 
151
+ def create_etc_symlinks
152
+ create_logrotate_symlinks
153
+ end
154
+
155
+ def create_logrotate_symlinks
156
+ logrotate_files.each do |path|
157
+ target_file = "#{stage}.#{project}.#{application}.#{path.basename}"
158
+ assure_symlink(path, logrotate_path.join(target_file))
159
+ end
160
+ end
161
+
151
162
  def update_releases_log
152
163
  execute %{echo "[$(date -u)][#{user}] #{release_log_message}" >> #{releases_log_path}}
153
164
  end
@@ -20,7 +20,7 @@ module Luban
20
20
 
21
21
  def fetch_revision
22
22
  # Use MD5 as the revision
23
- capture(:tar, "-cf - #{clone_path} 2>/dev/null | openssl md5")[0, rev_size]
23
+ capture(:tar, "-cf - #{clone_path} 2>/dev/null | openssl md5")[/\h+$/][0, rev_size]
24
24
  end
25
25
 
26
26
  def clone
@@ -3,8 +3,9 @@ module Luban
3
3
  class Command < Luban::CLI::Command
4
4
  module Tasks
5
5
  module Install
6
- %i(build destroy cleanup binstubs
7
- show_current show_summary which whence).each do |action|
6
+ Actions = %i(setup build destroy cleanup binstubs
7
+ show_current show_summary which whence)
8
+ Actions.each do |action|
8
9
  define_method(action) do |args:, opts:|
9
10
  raise NotImplementedError, "#{self.class.name}##{__method__} is an abstract method."
10
11
  end
@@ -69,7 +70,8 @@ module Luban
69
70
  end
70
71
 
71
72
  module Deploy
72
- %i(deploy).each do |action|
73
+ Actions = %i(deploy)
74
+ Actions.each do |action|
73
75
  define_method(action) do |args:, opts:|
74
76
  raise NotImplementedError, "#{self.class.name}##{__method__} is an abstract method."
75
77
  end
@@ -88,9 +90,10 @@ module Luban
88
90
  end
89
91
 
90
92
  module Control
91
- %i(start_process stop_process restart_process
92
- show_process_status test_process
93
- monitor_process unmonitor_process).each do |action|
93
+ Actions = %i(start_process stop_process kill_process
94
+ restart_process check_process
95
+ monitor_process unmonitor_process)
96
+ Actions.each do |action|
94
97
  define_method(action) do |args:, opts:|
95
98
  raise NotImplementedError, "#{self.class.name}##{__method__} is an abstract method."
96
99
  end
@@ -116,14 +119,14 @@ module Luban
116
119
  action! :restart_process
117
120
  end
118
121
 
119
- task :status do
120
- desc "Show process status"
121
- action! :show_process_status
122
+ task :kill do
123
+ desc "Kill process forcely"
124
+ action! :kill_process
122
125
  end
123
126
 
124
- task :test do
125
- desc "Test process"
126
- action! :test_process
127
+ task :status do
128
+ desc "Check process status"
129
+ action! :check_process
127
130
  end
128
131
 
129
132
  task :monitor do
@@ -151,7 +154,7 @@ module Luban
151
154
 
152
155
  def task(cmd, **opts, &blk)
153
156
  command(cmd, **opts, &blk).tap do |c|
154
- add_common_task_options(c)
157
+ add_common_task_options(c)
155
158
  if !c.summary.nil? and c.description.empty?
156
159
  c.long_desc "#{c.summary} in #{self.class.name}"
157
160
  end
@@ -174,10 +177,10 @@ module Luban
174
177
  end
175
178
  end
176
179
 
177
- def define_task_method(method, task: method, worker:, locally: false, &blk)
178
- define_method(method) do |args:, opts:|
179
- run_task(cmd: task, args: args, opts: opts, locally: locally,
180
- worker_class: self.class.worker_class(worker), &blk)
180
+ def dispatch_task(task, to:, as: task, locally: false, &blk)
181
+ define_method(task) do |args:, opts:|
182
+ run_task(cmd: as, args: args, opts: opts, locally: locally,
183
+ worker_class: self.class.worker_class(to), &blk)
181
184
  end
182
185
  end
183
186
  end
@@ -198,6 +201,7 @@ module Luban
198
201
  r = worker_class.new(task_msg.merge(backend: backend), &blk).run
199
202
  rescue StandardError => e
200
203
  r = {
204
+ hostname: backend.host.hostname,
201
205
  status: :failed,
202
206
  message: backtrace ? "#{e.message}\n#{e.backtrace.join("\n")}" : e.message,
203
207
  error: e
@@ -263,8 +267,8 @@ module Luban
263
267
  setup_control_tasks if controllable?
264
268
  end
265
269
 
266
- %i(install deploy control).each do |operation|
267
- define_method("setup_#{operation}_tasks") do
270
+ %i(install deploy control).each do |action|
271
+ define_method("setup_#{action}_tasks") do
268
272
  raise NotImplementedError, "#{self.class.name}##{__method__} is an abstract method."
269
273
  end
270
274
  end
@@ -339,9 +343,12 @@ module Luban
339
343
  sshkit.backend.configure do |backend|
340
344
  backend.pty = pty
341
345
  backend.connection_timeout = connection_timeout
342
- backend.ssh_options =
343
- backend.ssh_options.merge(user: user).merge!(ssh_options)
346
+ if backend.respond_to?(:ssh_options)
347
+ backend.ssh_options =
348
+ backend.ssh_options.merge(user: user).merge!(ssh_options)
349
+ end
344
350
  end
351
+ #bundle_bins.each { |cmd| sshkit.command_map.prefix[cmd.to_sym].push("bundle exec") }
345
352
  end
346
353
 
347
354
  configure_airbrussh if format == :airbrussh
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Package
4
- class Binary < Luban::Deployment::Command
4
+ class Base < Luban::Deployment::Command
5
5
  using Luban::CLI::CoreRefinements
6
6
 
7
7
  class << self
@@ -90,12 +90,12 @@ module Luban
90
90
 
91
91
  def versions; package_options.keys; end
92
92
 
93
- define_task_method("download_package", task: :download, worker: :installer, locally: true)
94
- define_task_method("install_package", task: :install, worker: :installer)
93
+ dispatch_task :download_package, to: :installer, as: :download, locally: true
94
+ dispatch_task :install_package, to: :installer, as: :install
95
95
 
96
96
  %i(uninstall cleanup_all update_binstubs
97
- get_summary which_current whence_origin).each do |m|
98
- define_task_method(m, worker: :installer)
97
+ get_summary which_current whence_origin).each do |task|
98
+ dispatch_task task, to: :installer
99
99
  end
100
100
 
101
101
  def install(args:, opts:)
@@ -200,6 +200,7 @@ module Luban
200
200
  def setup_install_tasks
201
201
  super
202
202
 
203
+ undef_task :setup
203
204
  undef_task :build
204
205
  undef_task :destroy
205
206
 
@@ -242,8 +243,6 @@ module Luban
242
243
  end
243
244
  end
244
245
  end
245
-
246
- Base = Binary
247
246
  end
248
247
  end
249
248
  end
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Package
4
- class Installer < Worker
4
+ class Installer
5
5
  # Shared library file extension name based on OS
6
6
  LibExtensions = {
7
7
  Linux: 'so', # Linux
@@ -32,14 +32,6 @@ module Luban
32
32
  @download_url ||= File.join(source_repo, source_url_root, src_file_name)
33
33
  end
34
34
 
35
- def install_path
36
- @install_path ||= package_versions_path.join(package_version)
37
- end
38
-
39
- def bin_path
40
- @bin_path ||= install_path.join('bin')
41
- end
42
-
43
35
  def lib_path
44
36
  @lib_path ||= install_path.join('lib')
45
37
  end
@@ -1,3 +1,11 @@
1
+ module Luban
2
+ module Deployment
3
+ module Package
4
+ class Installer < Worker; end
5
+ end
6
+ end
7
+ end
8
+
1
9
  require_relative 'installer/core'
2
10
  require_relative 'installer/paths'
3
11
  require_relative 'installer/install'
@@ -12,6 +12,12 @@ module Luban
12
12
  def worker_class(worker, **opts)
13
13
  Luban::Deployment::Package::Base.worker_class(worker, **opts)
14
14
  end
15
+
16
+ def default_executable(name)
17
+ define_method("#{name}_executable") do
18
+ @default_executable ||= bin_path.join(name)
19
+ end
20
+ end
15
21
  end
16
22
 
17
23
  def package_name; task.opts.name; end
@@ -40,6 +46,14 @@ module Luban
40
46
  @package_versions_path ||= package_path.join('versions')
41
47
  end
42
48
 
49
+ def install_path
50
+ @install_path ||= package_versions_path.join(package_version)
51
+ end
52
+
53
+ def bin_path
54
+ @bin_path ||= install_path.join('bin')
55
+ end
56
+
43
57
  def package_tmp_path
44
58
  @package_tmp_path ||= package_path.join('tmp')
45
59
  end
@@ -1,6 +1,5 @@
1
1
  require_relative 'package/dependency'
2
2
  require_relative 'package/dependency_set'
3
- require_relative 'package/binary'
4
- require_relative 'package/service'
3
+ require_relative 'package/base'
5
4
  require_relative 'package/worker'
6
5
  require_relative 'package/installer'
@@ -36,9 +36,7 @@ module Luban
36
36
  end
37
37
  end
38
38
 
39
- %i(build destroy_project cleanup binstubs
40
- show_current show_summary which whence
41
- ).each do |action|
39
+ (Luban::Deployment::Command::Tasks::Install::Actions | %i(destroy_project)).each do |action|
42
40
  define_method(action) do |args:, opts:|
43
41
  apps.each_value do |app|
44
42
  app.send(__method__, args: args, opts: opts) if app.installable?
@@ -48,6 +46,22 @@ module Luban
48
46
 
49
47
  alias_method :destroy, :destroy_project
50
48
 
49
+ Luban::Deployment::Command::Tasks::Deploy::Actions.each do |action|
50
+ define_method(action) do |args:, opts:|
51
+ apps.each_value do |app|
52
+ app.send(__method__, args: args, opts: opts) if app.deployable?
53
+ end
54
+ end
55
+ end
56
+
57
+ Luban::Deployment::Command::Tasks::Control::Actions.each do |action|
58
+ define_method(action) do |args:, opts:|
59
+ apps.each_value do |app|
60
+ app.send(__method__, args: args, opts: opts) if app.controllable?
61
+ end
62
+ end
63
+ end
64
+
51
65
  protected
52
66
 
53
67
  def validate_parameters
@@ -0,0 +1,49 @@
1
+ module Luban
2
+ module Deployment
3
+ module Service
4
+ class Base < Luban::Deployment::Package::Base
5
+ include Luban::Deployment::Command::Tasks::Deploy
6
+ include Luban::Deployment::Command::Tasks::Control
7
+
8
+ ControlActions = Luban::Deployment::Command::Tasks::Control::Actions
9
+ ProfileActions = %i(update_profile)
10
+
11
+ (ControlActions | ProfileActions).each do |m|
12
+ define_method(m) do |args:, opts:|
13
+ if current_version
14
+ send("#{__method__}!", args: args, opts: opts.merge(version: current_version))
15
+ else
16
+ abort "Aborted! No current version of #{display_name} is specified."
17
+ end
18
+ end
19
+ end
20
+
21
+ protected
22
+
23
+ def on_configure
24
+ super
25
+ include_default_templates_path if respond_to?(:default_templates_path, true)
26
+ end
27
+
28
+ def include_default_templates_path
29
+ if default_templates_path.is_a?(Pathname)
30
+ default_templates_paths.unshift(default_templates_path)
31
+ else
32
+ abort "Aborted! Default templates path for #{self.class.name} MUST be a Pathname."
33
+ end
34
+ end
35
+
36
+ def set_parameters
37
+ super
38
+ linked_dirs.push('log', 'pids')
39
+ end
40
+
41
+ ControlActions.each do |task|
42
+ dispatch_task "#{task}!", to: :controller, as: task
43
+ end
44
+
45
+ dispatch_task :update_profile!, to: :configurator, as: :update_profile, locally: true
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,57 @@
1
+ module Luban
2
+ module Deployment
3
+ module Service
4
+ class Configurator < Worker
5
+ def stage_profile_path
6
+ @stage_profile_path ||=
7
+ config_finder[:application].stage_profile_path.join(service_name)
8
+ end
9
+
10
+ def profile_templates_path
11
+ @profile_templates_path ||=
12
+ config_finder[:application].profile_templates_path.join(service_name)
13
+ end
14
+
15
+ def stage_profile_templates_path
16
+ @stage_profile_templates_path ||=
17
+ config_finder[:application].stage_profile_templates_path.join(service_name)
18
+ end
19
+
20
+ def profile_templates(format: "erb")
21
+ return @profile_templates unless @profile_templates.nil?
22
+ @profile_templates = []
23
+ [profile_templates_path, stage_profile_templates_path].each do |path|
24
+ Dir.chdir(path) { @profile_templates |= Dir["**/*.#{format}"] } if path.directory?
25
+ end
26
+ @profile_templates
27
+ end
28
+
29
+ def update_profile
30
+ assure_dirs(stage_profile_path)
31
+ render_profile
32
+ update_logrotate_files
33
+ end
34
+
35
+ protected
36
+
37
+ def render_profile
38
+ profile_templates.each { |template_file| render_profile_by_template(template_file) }
39
+ end
40
+
41
+ def render_profile_by_template(template_file)
42
+ profile_file = stage_profile_path.join(template_file).sub_ext('')
43
+ assure_dirs(profile_file.dirname)
44
+ upload_by_template(file_to_upload: profile_file,
45
+ template_file: find_template_file(File.join(service_name, template_file)),
46
+ auto_revision: true)
47
+ end
48
+
49
+ def update_logrotate_files
50
+ if file?(stage_profile_path.join(logrotate_file_name))
51
+ logrotate_files.push(logrotate_file_path)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,99 @@
1
+ module Luban
2
+ module Deployment
3
+ module Service
4
+ class Controller < Worker
5
+ %i(process_stopped? process_started?
6
+ monitor_process unmonitor_process).each do |m|
7
+ define_method(m) do
8
+ raise NotImplementedError, "#{self.class.name}##{__method__} is an abstract method."
9
+ end
10
+ end
11
+
12
+ def start_process
13
+ if process_started?
14
+ update_result "Skipped! Already started #{package_full_name}", status: :skipped
15
+ return
16
+ end
17
+
18
+ output = start_process!
19
+ if check_until { process_started? }
20
+ update_result "Successfully started #{package_full_name}: #{output}"
21
+ else
22
+ update_result "Failed to start #{package_full_name}: #{output}",
23
+ status: :failed, level: :error
24
+ end
25
+ end
26
+
27
+ def stop_process
28
+ if process_stopped?
29
+ update_result "Skipped! Already stopped #{package_full_name}", status: :skipped
30
+ return
31
+ end
32
+
33
+ output = stop_process!
34
+ if check_until { process_stopped? }
35
+ update_result "Successfully stopped #{package_full_name}: #{output}"
36
+ else
37
+ update_result "Failed to stop #{package_full_name}: #{output}",
38
+ status: :failed, level: :error
39
+ end
40
+ end
41
+
42
+ def restart_process
43
+ if process_started?
44
+ output = stop_process!
45
+ unless check_until { process_stopped? }
46
+ update_result "Failed to stop #{package_full_name}: #{output}",
47
+ status: :failed, level: :error
48
+ return
49
+ end
50
+ end
51
+
52
+ output = start_process!
53
+ if check_until { process_started? }
54
+ update_result "Successfully restarted #{package_full_name}: #{output}"
55
+ else
56
+ update_result "Failed to restart #{package_full_name}: #{output}",
57
+ status: :failed, level: :error
58
+ end
59
+ end
60
+
61
+ def check_process
62
+ update_result check_process!
63
+ end
64
+
65
+ def kill_process
66
+ output = kill_process!
67
+ if check_until { process_stopped? }
68
+ update_result "Successfully kill processs (#{output})."
69
+ else
70
+ update_result "Failed to kill process: #{output}"
71
+ end
72
+ end
73
+
74
+ def check_until(pending_seconds = 30)
75
+ succeeded = false
76
+ pending_seconds.times do
77
+ sleep 1
78
+ break if (succeeded = yield)
79
+ end
80
+ succeeded
81
+ end
82
+
83
+ protected
84
+
85
+ %i(start_process! stop_process! check_process!).each do |m|
86
+ define_method(m) do
87
+ raise NotImplementedError, "#{self.class.name}##{__method__} is an abstract method."
88
+ end
89
+ end
90
+
91
+ def kill_process!
92
+ pid = capture(pid_file_path)
93
+ output = capture(:kill, "-9 #{pid}")
94
+ output.empty? ? pid : output
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,9 @@
1
+ module Luban
2
+ module Deployment
3
+ module Service
4
+ class Installer < Luban::Deployment::Package::Installer
5
+ include Paths
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ module Luban
2
+ module Deployment
3
+ module Service
4
+ module Paths
5
+ include Luban::Deployment::Worker::Paths::Remote::Service
6
+
7
+ def service_name
8
+ @service_name = package_name.downcase
9
+ end
10
+
11
+ def profile_path
12
+ @profile_path ||= super.join(service_name)
13
+ end
14
+
15
+ def control_file_name
16
+ @control_file_name ||= "#{service_name}.conf"
17
+ end
18
+
19
+ def logrotate_file_name
20
+ @logrotate_file_name ||= "#{service_name}.logrotate"
21
+ end
22
+
23
+ def pid_file_name
24
+ @pid_file_name ||= "#{service_name}.pid"
25
+ end
26
+
27
+ def log_file_name
28
+ @log_file_name ||= "#{service_name}.log"
29
+ end
30
+ end
31
+
32
+ class Worker < Luban::Deployment::Package::Worker
33
+ include Paths
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'service/base'
2
+ require_relative 'service/worker'
3
+ require_relative 'service/installer'
4
+ require_relative 'service/configurator'
5
+ require_relative 'service/controller'
@@ -2,3 +2,4 @@ require_relative 'cli/command'
2
2
  require_relative 'cli/project'
3
3
  require_relative 'cli/application'
4
4
  require_relative 'cli/package'
5
+ require_relative 'cli/service'
@@ -70,11 +70,13 @@ module Luban
70
70
 
71
71
  def find_template_file(file_name)
72
72
  path = find_template_file_by_config_finder(file_name) ||
73
- find_default_template_file(file_name)
73
+ Finder.find_default_template_file(file_name)
74
74
  raise RuntimeError, "Template file is NOT found: #{file_name}." if path.nil?
75
75
  path
76
76
  end
77
77
 
78
+ def default_templates_paths; Finder.default_templates_paths; end
79
+
78
80
  protected
79
81
 
80
82
  def find_template_file_by_config_finder(file_name)
@@ -82,19 +84,48 @@ module Luban
82
84
  config_finder[:project].find_template_file(file_name)
83
85
  end
84
86
 
85
- def find_default_template_file(file_name)
86
- path = File.expand_path(File.join(File.dirname(__FILE__), '..',
87
- 'templates', file_name))
88
- return path if File.file?(path)
89
- end
90
-
91
87
  class Finder
88
+ def self.default_templates_paths
89
+ @default_templates_paths ||=
90
+ [Pathname.new(File.join(File.dirname(__FILE__), '..', 'templates')).realpath]
91
+ end
92
+
93
+ def self.find_default_template_file(file_name)
94
+ path = default_templates_paths.find { |p| p.join(file_name).file? }
95
+ return path.join(file_name) unless path.nil?
96
+ end
97
+
92
98
  class Project < Finder
93
99
  def base_path; base_path ||= target.work_dir; end
94
100
  end
95
101
 
96
102
  class Application < Finder
103
+ attr_reader :profile_templates_path
104
+ attr_reader :stage_profile_path
105
+ attr_reader :stage_profile_templates_path
106
+
97
107
  def base_path; base_path ||= target.apps_path.join(target.application); end
108
+
109
+ def has_profile?
110
+ stage_profile_templates_path.directory? or
111
+ stage_profile_path.directory? or
112
+ profile_templates_path.directory?
113
+ end
114
+
115
+ def find_template_file(file_name)
116
+ return file_path if (file_path = stage_profile_templates_path.join(file_name)).file?
117
+ return file_path if (file_path = profile_templates_path.join(file_name)).file?
118
+ super
119
+ end
120
+
121
+ protected
122
+
123
+ def set_config_paths
124
+ super
125
+ @profile_templates_path = @templates_path.join('profile')
126
+ @stage_profile_path = @stage_config_path.join('profile')
127
+ @stage_profile_templates_path = @stage_templates_path.join('profile')
128
+ end
98
129
  end
99
130
 
100
131
  def self.project(target); Project.new(target); end
@@ -137,8 +168,8 @@ module Luban
137
168
  end
138
169
 
139
170
  def find_template_file(file_name)
140
- return file_path if File.file?(file_path = stage_templates_path.join(file_name))
141
- return file_path if File.file?(file_path = templates_path.join(file_name))
171
+ return file_path if (file_path = stage_templates_path.join(file_name)).file?
172
+ return file_path if (file_path = templates_path.join(file_name)).file?
142
173
  end
143
174
 
144
175
  protected
@@ -131,7 +131,7 @@ module Luban
131
131
  end
132
132
 
133
133
  def revision_match?(file_to_upload, revision)
134
- file?(file_to_upload) and match?("grep \"Revision: \" #{file_to_upload}", revision)
134
+ file?(file_to_upload) and match?("grep \"Revision: \" #{file_to_upload}; true", revision)
135
135
  end
136
136
 
137
137
  [:test, :make, :within, :with, :as, :execute,
@@ -142,7 +142,7 @@ module Luban
142
142
  end
143
143
 
144
144
  def capture(*args, &blk)
145
- backend.capture(*args, &blk).chomp
145
+ backend.capture(*args, raise_on_non_zero_exit: false, &blk).chomp
146
146
  end
147
147
 
148
148
  def md5_matched?(file_path, md5)
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Packages
4
- class Bundler < Luban::Deployment::Package::Binary
4
+ class Bundler < Luban::Deployment::Package::Base
5
5
  protected
6
6
 
7
7
  def setup_install_tasks
@@ -26,9 +26,7 @@ module Luban
26
26
  parent.install_path
27
27
  end
28
28
 
29
- def bundler_executable
30
- @bundler_executable ||= bin_path.join('bundle')
31
- end
29
+ default_executable 'bundler'
32
30
 
33
31
  def gem_executable
34
32
  parent.gem_executable
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Packages
4
- class Git < Luban::Deployment::Package::Binary
4
+ class Git < Luban::Deployment::Package::Base
5
5
  apply_to :all do
6
6
  before_install do
7
7
  depend_on 'openssl', version: '1.0.2g'
@@ -9,9 +9,7 @@ module Luban
9
9
  end
10
10
 
11
11
  class Installer < Luban::Deployment::Package::Installer
12
- def git_executable
13
- @git_executable ||= bin_path.join('git')
14
- end
12
+ default_executable 'git'
15
13
 
16
14
  def source_repo
17
15
  @source_repo ||= "https://www.kernel.org"
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Packages
4
- class Openssl < Luban::Deployment::Package::Binary
4
+ class Openssl < Luban::Deployment::Package::Base
5
5
  class Installer < Luban::Deployment::Package::Installer
6
6
  OSXArchArgs = {
7
7
  x86_64: %w(darwin64-x86_64-cc enable-ec_nistp_64_gcc_128),
@@ -13,9 +13,7 @@ module Luban
13
13
 
14
14
  end
15
15
 
16
- def openssl_executable
17
- @openssl_executable ||= bin_path.join('openssl')
18
- end
16
+ default_executable 'openssl'
19
17
 
20
18
  def source_repo
21
19
  #@source_repo ||= "https://www.openssl.org"
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Packages
4
- class Ruby < Luban::Deployment::Package::Binary
4
+ class Ruby < Luban::Deployment::Package::Base
5
5
  apply_to '1.8.6' do
6
6
  after_install do
7
7
  depend_on 'rubygems', version: '1.3.7'
@@ -73,9 +73,7 @@ module Luban
73
73
  task.opts.install_doc
74
74
  end
75
75
 
76
- def ruby_executable
77
- @ruby_executable ||= bin_path.join('ruby')
78
- end
76
+ default_executable 'ruby'
79
77
 
80
78
  def gem_executable
81
79
  @gem_executable ||= bin_path.join('gem')
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Packages
4
- class Rubygems < Luban::Deployment::Package::Binary
4
+ class Rubygems < Luban::Deployment::Package::Base
5
5
  protected
6
6
 
7
7
  def setup_install_tasks
@@ -22,10 +22,8 @@ module Luban
22
22
  parent.install_path
23
23
  end
24
24
 
25
- def rubygems_executable
26
- @rubygems_executable ||= bin_path.join('gem')
27
- end
28
-
25
+ default_executable 'gem'
26
+
29
27
  def ruby_executable
30
28
  parent.ruby_executable
31
29
  end
@@ -44,8 +42,8 @@ module Luban
44
42
  end
45
43
 
46
44
  def installed?
47
- return false unless file?(rubygems_executable)
48
- match?("#{rubygems_executable} -v", package_version)
45
+ return false unless file?(gem_executable)
46
+ match?("#{gem_executable} -v", package_version)
49
47
  end
50
48
 
51
49
  protected
@@ -1,7 +1,7 @@
1
1
  module Luban
2
2
  module Deployment
3
3
  module Packages
4
- class Yaml < Luban::Deployment::Package::Binary
4
+ class Yaml < Luban::Deployment::Package::Base
5
5
  class Installer < Luban::Deployment::Package::Installer
6
6
  def header_file
7
7
  @header_file ||= include_path.join('yaml.h')
@@ -108,6 +108,7 @@ module Luban
108
108
  parameter :keep_releases
109
109
  parameter :linked_dirs
110
110
  parameter :linked_files
111
+ parameter :logrotate_files
111
112
 
112
113
  protected
113
114
 
@@ -116,6 +117,7 @@ module Luban
116
117
  set_default :keep_releases, 3
117
118
  set_default :linked_dirs, []
118
119
  set_default :linked_files, []
120
+ set_default :logrotate_files, []
119
121
 
120
122
  setup_default_application_config_finder
121
123
  end
@@ -1,5 +1,5 @@
1
1
  module Luban
2
2
  module Deployment
3
- VERSION = "0.3.3"
3
+ VERSION = "0.3.5"
4
4
  end
5
5
  end
@@ -60,7 +60,7 @@ module Luban
60
60
  task.result.tap do |r|
61
61
  r.status = status
62
62
  r.level = level
63
- r.message = message unless message.nil?
63
+ r.message = message unless message.nil? or !r.message.nil?
64
64
  attrs.each_pair { |k, v| r.send("#{k}=", v) }
65
65
  send(level, message) unless message.nil? or message.empty?
66
66
  end
@@ -25,6 +25,10 @@ module Luban
25
25
  @etc_path ||= luban_root_path.join('etc')
26
26
  end
27
27
 
28
+ def logrotate_path
29
+ @logrotate_path = etc_path.join('logrotate')
30
+ end
31
+
28
32
  def tmp_path
29
33
  @tmp_path ||= luban_root_path.join('tmp')
30
34
  end
@@ -68,6 +72,52 @@ module Luban
68
72
  def luban_install_path
69
73
  @luban_install_path ||= project_path.join('.luban')
70
74
  end
75
+
76
+ module Service
77
+ def profile_path
78
+ @profile_path ||= shared_path.join('profile')
79
+ end
80
+
81
+ def log_path
82
+ @log_path ||= shared_path.join('log')
83
+ end
84
+
85
+ def log_file_path
86
+ @log_file_path ||= log_path.join(log_file_name)
87
+ end
88
+
89
+ def log_file_name
90
+ raise NotImplementedError, "#{self.class.name}#log_file_name is an abstract method."
91
+ end
92
+
93
+ def pids_path
94
+ @pids_path ||= shared_path.join('pids')
95
+ end
96
+
97
+ def pid_file_path
98
+ @pid_file_path ||= pids_path.join(pid_file_name)
99
+ end
100
+
101
+ def pid_file_name
102
+ raise NotImplementedError, "#{self.class.name}#pid_file_name is an abstract method."
103
+ end
104
+
105
+ def control_file_path
106
+ @control_file_path ||= profile_path.join(control_file_name)
107
+ end
108
+
109
+ def control_file_name
110
+ raise NotImplementedError, "#{self.class.name}#control_file_name is an abstract method."
111
+ end
112
+
113
+ def logrotate_file_path
114
+ @logrotate_file_path ||= profile_path.join(logrotate_file_name)
115
+ end
116
+
117
+ def logrotate_file_name
118
+ raise NotImplementedError, "#{self.class.name}#logrotate_file_name is an abstract method."
119
+ end
120
+ end
71
121
  end
72
122
  end
73
123
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: luban
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rubyist Lei
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-18 00:00:00.000000000 Z
11
+ date: 2016-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: luban-cli
@@ -110,16 +110,21 @@ files:
110
110
  - lib/luban/deployment/cli/application/scm/rsync.rb
111
111
  - lib/luban/deployment/cli/command.rb
112
112
  - lib/luban/deployment/cli/package.rb
113
- - lib/luban/deployment/cli/package/binary.rb
113
+ - lib/luban/deployment/cli/package/base.rb
114
114
  - lib/luban/deployment/cli/package/dependency.rb
115
115
  - lib/luban/deployment/cli/package/dependency_set.rb
116
116
  - lib/luban/deployment/cli/package/installer.rb
117
117
  - lib/luban/deployment/cli/package/installer/core.rb
118
118
  - lib/luban/deployment/cli/package/installer/install.rb
119
119
  - lib/luban/deployment/cli/package/installer/paths.rb
120
- - lib/luban/deployment/cli/package/service.rb
121
120
  - lib/luban/deployment/cli/package/worker.rb
122
121
  - lib/luban/deployment/cli/project.rb
122
+ - lib/luban/deployment/cli/service.rb
123
+ - lib/luban/deployment/cli/service/base.rb
124
+ - lib/luban/deployment/cli/service/configurator.rb
125
+ - lib/luban/deployment/cli/service/controller.rb
126
+ - lib/luban/deployment/cli/service/installer.rb
127
+ - lib/luban/deployment/cli/service/worker.rb
123
128
  - lib/luban/deployment/configuration.rb
124
129
  - lib/luban/deployment/configuration/core.rb
125
130
  - lib/luban/deployment/configuration/filter.rb
@@ -166,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
171
  version: '0'
167
172
  requirements: []
168
173
  rubyforge_project:
169
- rubygems_version: 2.4.5
174
+ rubygems_version: 2.5.1
170
175
  signing_key:
171
176
  specification_version: 4
172
177
  summary: Ruby framework for server automation and application deployment
@@ -1,17 +0,0 @@
1
- module Luban
2
- module Deployment
3
- module Package
4
- class Service < Binary
5
- include Luban::Deployment::Command::Tasks::Deploy
6
- include Luban::Deployment::Command::Tasks::Control
7
-
8
- %i(deploy).each do |m|
9
- define_task_method(m, worker: :deployer)
10
- end
11
-
12
- protected
13
-
14
- end
15
- end
16
- end
17
- end