luban 0.3.3 → 0.3.5

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 (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