luban 0.8.10 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 93138388605dfd36238452d9c61eda0ba31c838f
4
- data.tar.gz: bfe1d55d44ef71c128c855115aacd1a679b998a4
3
+ metadata.gz: b1c840fa119a9368e8e98cae2dfc701d2f31ead8
4
+ data.tar.gz: 10bc13a1c416506baae0a5aff9e88a17a61ee604
5
5
  SHA512:
6
- metadata.gz: 93051b080c0bfca59e1f44fed83e752be9271b5849feb63927f50c94bbeef072165c1064ba779101c7f695e636406a419616b2b289ebe2624a0db342ed7bba17
7
- data.tar.gz: 0e0aa51ed17722f15313f15490e739079efd8180c0e59883847e75cd2ebb4336cce0927b9d637741cee97f1497f5ff6cde50a5e7719f4cca12540cf5c0eda640
6
+ metadata.gz: 95ce838aecc0b93916935fc3469366826403599abcef453b8cada2b83063329eca02b7d0b25b0cbeb3e339a2cc5eb016f0f9e50c53947e64077ebfaf3d535718
7
+ data.tar.gz: af1aae4d01bb04f54097738a7a23c8b184842895e1e67be8705b95e15e523cbc9f1ae49ddf80dab129a1bad6691e5f5d0a3feb138258a2ac49161548b5b59ff9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Change log
2
2
 
3
+ ## Version 0.9.0 (Oct 12, 2016)
4
+
5
+ New features:
6
+ * Added package for Logrotate
7
+ * Added dependent package for Popt
8
+ * Added support for log archival which is done thru Uber
9
+ * Added two convenient methods, #touch and #truncate, in module Utils
10
+
11
+ Minor enhancements:
12
+ * Set keep_releases differently for app and profile publication
13
+ * Made application always deployable
14
+ * Application has/has no cronjobs to update which implies deployable
15
+ * Deprecated symlinks for logrotate configuration files
16
+ * As a result, directory "etc" is removed as well since it is no more necessary
17
+ * No more place holder cronjob entries if there are no more cronjobs defined
18
+ * Refactored profile templates handling in service configurator
19
+ * Cleaned up profile files that have been excluded
20
+ * Made luban_roles as the default roles when setting up cronjobs
21
+ * Added back support for build environment variables like LDFLAGS/CFLAGS
22
+ * Upgraded OpenSSL for Ruby to version 1.0.2j
23
+ * Upgraded Bundler for Ruby to version 1.13.3
24
+ * Added Rubygems dependency for Ruby (version >= 1.9.3)
25
+ * As a side effect, package option #rubygems for Ruby can be set for all Ruby versions
26
+ * Minor code cleanup
27
+
28
+ Bug fixes:
29
+ * Added an extra validation for URL existence test
30
+
3
31
  ## Version 0.8.10 (Sept 29, 2016)
4
32
 
5
33
  Minor enhancements:
@@ -56,7 +56,7 @@ module Luban
56
56
  def has_services?; !services.empty?; end
57
57
 
58
58
  def provisionable?; has_packages?; end
59
- def deployable?; has_source? or has_profile? end
59
+ def deployable?; true; end
60
60
  def controllable?; has_source? or has_services?; end
61
61
 
62
62
  def use_package?(package_name, package_version, servers: [])
@@ -20,13 +20,11 @@ module Luban
20
20
  end
21
21
 
22
22
  def destroy_project
23
- rm(etc_path.join('*', "#{stage}.#{project}.*"))
24
23
  rmdir(project_path)
25
24
  update_result "The project environment is destroyed."
26
25
  end
27
26
 
28
27
  def destroy_app
29
- rm(etc_path.join('*', "#{stage}.#{project}.#{application}.*"))
30
28
  rmdir(app_path)
31
29
  update_result "The application environment is destroyed."
32
30
  end
@@ -39,7 +37,7 @@ module Luban
39
37
  protected
40
38
 
41
39
  def bootstrap
42
- assure_dirs(logrotate_path, downloads_path,
40
+ assure_dirs(downloads_path, archived_logs_path,
43
41
  tmp_path, app_bin_path, app_tmp_path,
44
42
  releases_path, shared_path)
45
43
  end
@@ -55,7 +55,11 @@ module Luban
55
55
  return
56
56
  end
57
57
  if updated?
58
- update_result "Skipped! ALREADY updated crontab.", status: :skipped
58
+ if has_cronjobs?
59
+ update_result "Skipped! ALREADY updated crontab.", status: :skipped
60
+ else
61
+ update_result "Skipped! No crontab for #{user}.", status: :skipped
62
+ end
59
63
  return
60
64
  end
61
65
 
@@ -86,11 +90,19 @@ module Luban
86
90
 
87
91
  def deploy_cronjobs!
88
92
  rm(crontab_file_path) if force?
89
- upload_by_template(file_to_upload: crontab_file_path,
90
- template_file: crontab_template_file,
91
- header_file: crontab_header_template_file,
92
- footer_file: crontab_footer_template_file,
93
- auto_revision: true)
93
+ if has_cronjobs?
94
+ upload_by_template(file_to_upload: crontab_file_path,
95
+ template_file: crontab_template_file,
96
+ header_file: crontab_header_template_file,
97
+ footer_file: crontab_footer_template_file,
98
+ auto_revision: true)
99
+ else
100
+ if file?(crontab_file_path, "-s")
101
+ truncate(crontab_file_path)
102
+ else
103
+ touch(crontab_file_path) unless file?(crontab_file_path)
104
+ end
105
+ end
94
106
  end
95
107
 
96
108
  def crontab_entry(command:, schedule:, output: "", type: :shell, disabled: false)
@@ -101,6 +113,7 @@ module Luban
101
113
  unless respond_to?(command_composer)
102
114
  abort "Aborted! Unknown cronjob type: #{type.inspect}"
103
115
  end
116
+ command = instance_exec(&command) if command.respond_to?(:call)
104
117
  command = send(command_composer, command, output: output)
105
118
  entry = "#{schedule} #{command}"
106
119
  disabled ? "# DISABLED - #{entry}" : entry
@@ -112,15 +125,21 @@ module Luban
112
125
  found = false
113
126
  crontab = crontab.split("\n").inject([]) do |lines, line|
114
127
  if found || line == crontab_open
115
- lines << new_crontab unless (found = line != crontab_close)
128
+ unless (found = line != crontab_close)
129
+ lines << new_crontab unless new_crontab.empty?
130
+ end
116
131
  else
117
132
  lines << line
118
133
  end
119
134
  lines
120
135
  end
121
- crontab << new_crontab unless crontab.include?(new_crontab)
122
- upload!(StringIO.new(crontab.join("\n")), tmp_crontab_file_path)
123
- test(:crontab, tmp_crontab_file_path, "2>&1")
136
+ crontab << new_crontab unless new_crontab.empty? or crontab.include?(new_crontab)
137
+ if crontab.empty?
138
+ test(:crontab, "-r", "2>&1")
139
+ else
140
+ upload!(StringIO.new(crontab.join("\n")), tmp_crontab_file_path)
141
+ test(:crontab, tmp_crontab_file_path, "2>&1")
142
+ end
124
143
  ensure
125
144
  rm(tmp_crontab_file_path)
126
145
  end
@@ -92,7 +92,7 @@ module Luban
92
92
 
93
93
  def publish!
94
94
  rollout_release
95
- cleanup_releases
95
+ send("cleanup_#{release_type}_releases")
96
96
  end
97
97
 
98
98
  def rollout_release
@@ -100,7 +100,7 @@ module Luban
100
100
  upload!(release_package_path.to_s, upload_to.to_s)
101
101
  if md5_matched?(upload_to, release_md5) and
102
102
  test(:tar, "-xzf #{upload_to} -C #{releases_path}")
103
- execute(:touch, release_path)
103
+ touch(release_path)
104
104
  create_symlinks
105
105
  update_releases_log
106
106
  else
@@ -119,7 +119,6 @@ module Luban
119
119
 
120
120
  def create_profile_symlinks
121
121
  create_release_symlink(shared_path)
122
- create_etc_symlinks
123
122
  end
124
123
 
125
124
  def create_app_symlinks
@@ -135,23 +134,13 @@ module Luban
135
134
 
136
135
  def create_symlinks_for_linked_dirs
137
136
  create_linked_dirs(linked_dirs, from: shared_path, to: release_path)
137
+ assure_symlink(archived_logs_path, log_path.join(archived_logs_path.basename))
138
138
  end
139
139
 
140
140
  def create_symlinks_for_linked_files
141
141
  create_linked_files(linked_files, from: profile_path, to: release_path.join('config'))
142
142
  end
143
143
 
144
- def create_etc_symlinks
145
- create_logrotate_symlinks
146
- end
147
-
148
- def create_logrotate_symlinks
149
- logrotate_files.each do |path|
150
- target_file = "#{stage}.#{project}.#{application}.#{path.basename}"
151
- assure_symlink(path, logrotate_path.join(target_file))
152
- end
153
- end
154
-
155
144
  def update_releases_log
156
145
  execute %{echo "[$(date -u)][#{user}] #{release_log_message}" >> #{releases_log_path}}
157
146
  end
@@ -160,13 +149,16 @@ module Luban
160
149
  "#{release_name} in #{stage} #{project} is published successfully."
161
150
  end
162
151
 
163
- def cleanup_releases(keep_releases = 5)
152
+ def cleanup_releases(keep_releases = 1)
164
153
  files = capture(:ls, '-xtd', releases_path.join("#{release_version}-*")).split(" ")
165
154
  if files.count > keep_releases
166
155
  files.last(files.count - keep_releases).each { |f| rmdir(f) }
167
156
  end
168
157
  end
169
158
 
159
+ def cleanup_app_releases; cleanup_releases(5); end
160
+ def cleanup_profile_releases; cleanup_releases; end
161
+
170
162
  def bundle_gems
171
163
  assure_dirs(bundle_config_path, gems_cache_path, bundle_path)
172
164
  sync_gems_cache
@@ -42,6 +42,15 @@ module Luban
42
42
  def bundle_command(cmd, **opts)
43
43
  shell_command("#{bundle_executable} exec #{cmd}", **opts)
44
44
  end
45
+
46
+ def app_archives_path
47
+ @app_archives_path ||=
48
+ archives_path.join("#{stage}.#{project}", application, hostname)
49
+ end
50
+
51
+ def archived_logs_path
52
+ @archived_logs_path ||= app_archives_path.join('archived_logs')
53
+ end
45
54
  end
46
55
  end
47
56
  end
@@ -203,7 +203,7 @@ module Luban
203
203
 
204
204
  def has_cronjobs?; !cronjobs.empty?; end
205
205
 
206
- def cronjob(roles: nil, hosts: nil, **job)
206
+ def cronjob(roles: luban_roles, hosts: nil, **job)
207
207
  validate_cronjob(job)
208
208
  roles = Array(roles)
209
209
  hosts = Array(hosts)
@@ -46,8 +46,7 @@ module Luban
46
46
  def configure_build_env_variables
47
47
  @build_env_vars = {
48
48
  ldflags: [ENV['LDFLAGS'].to_s],
49
- cflags: [ENV['CFLAGS'].to_s],
50
- cppflags: [ENV['CPPFLAGS'].to_s]
49
+ cflags: [ENV['CFLAGS'].to_s]
51
50
  }
52
51
  if child?
53
52
  configure_parent_build_env_variables
@@ -58,7 +57,6 @@ module Luban
58
57
  def configure_parent_build_env_variables
59
58
  parent.build_env_vars[:ldflags] << "-L#{lib_path}"
60
59
  parent.build_env_vars[:cflags] << "-I#{include_path}"
61
- parent.build_env_vars[:cppflags] << "-I#{include_path}"
62
60
  end
63
61
 
64
62
  def configure_parent_build_options
@@ -67,6 +65,13 @@ module Luban
67
65
  end
68
66
  end
69
67
 
68
+ def compose_build_env_variables
69
+ build_env_vars.inject({}) do |vars, (k, v)|
70
+ vars[k] = "#{v.join(' ').strip}" unless v.all?(&:empty?)
71
+ vars
72
+ end
73
+ end
74
+
70
75
  def configure_build_options
71
76
  @configure_opts = default_configure_opts
72
77
  @configure_opts |= task.opts.configure_opts unless task.opts.configure_opts.nil?
@@ -302,7 +302,7 @@ module Luban
302
302
  end
303
303
 
304
304
  def bootstrap_install
305
- assure_dirs(etc_path, tmp_path, app_bin_path,
305
+ assure_dirs(tmp_path, app_bin_path,
306
306
  package_tmp_path, install_path, install_log_path)
307
307
  end
308
308
 
@@ -18,15 +18,23 @@ module Luban
18
18
  config_finder[:application].stage_profile_templates_path.join(profile_name)
19
19
  end
20
20
 
21
- def profile_templates(format: "erb")
22
- return @profile_templates unless @profile_templates.nil?
23
- @profile_templates = []
21
+ def available_profile_templates(format: "erb")
22
+ return @available_profile_templates unless @available_profile_templates.nil?
23
+ templates = []
24
24
  [profile_templates_path, stage_profile_templates_path].each do |path|
25
- Dir.chdir(path) { @profile_templates |= Dir["**/*.#{format}"] } if path.directory?
26
- end
27
- @profile_templates.tap do |templates|
28
- templates.reject! { |t| exclude_template?(t) }
25
+ Dir.chdir(path) { templates |= Dir["**/*.#{format}"] } if path.directory?
29
26
  end
27
+ @available_profile_templates = templates
28
+ end
29
+
30
+ def profile_templates(format: "erb")
31
+ @profile_templates ||=
32
+ available_profile_templates(format: format).reject { |t| exclude_template?(t) }
33
+ end
34
+
35
+ def excluded_profile_templates(format: "erb")
36
+ @excluded_profile_templates ||=
37
+ available_profile_templates(format: format).select { |t| exclude_template?(t) }
30
38
  end
31
39
 
32
40
  def exclude_template?(template); false; end
@@ -43,7 +51,7 @@ module Luban
43
51
  def update_profile
44
52
  assure_dirs(stage_profile_path)
45
53
  render_profile
46
- update_logrotate_files
54
+ cleanup_profile
47
55
  end
48
56
 
49
57
  protected
@@ -79,9 +87,10 @@ module Luban
79
87
  auto_revision: true)
80
88
  end
81
89
 
82
- def update_logrotate_files
83
- if file?(stage_profile_path.join(logrotate_file_name))
84
- logrotate_files.push(logrotate_file_path)
90
+ def cleanup_profile
91
+ excluded_profile_templates.each do |template_file|
92
+ profile_file = stage_profile_path.join(template_file).sub_ext('')
93
+ rm(profile_file) if file?(profile_file)
85
94
  end
86
95
  end
87
96
  end
@@ -73,14 +73,6 @@ module Luban
73
73
  def control_file_name
74
74
  @control_file_name ||= "#{service_name}.conf"
75
75
  end
76
-
77
- def logrotate_file_path
78
- @logrotate_file_path ||= profile_path.join(logrotate_file_name)
79
- end
80
-
81
- def logrotate_file_name
82
- @logrotate_file_name ||= "#{service_name}.logrotate"
83
- end
84
76
  end
85
77
 
86
78
  include Base
@@ -23,7 +23,7 @@ module Luban
23
23
  assure_dirs(target_path.dirname)
24
24
  rmdir(target_path) if directory?(target_path)
25
25
  source_path = from.join(path)
26
- assure_symlink(source_path, target_path) #if directory?(source_path)
26
+ assure_symlink(source_path, target_path)
27
27
  end
28
28
  end
29
29
 
@@ -33,7 +33,7 @@ module Luban
33
33
  assure_dirs(target_path.dirname)
34
34
  rm(target_path) if file?(target_path)
35
35
  source_path = from.join(path)
36
- assure_symlink(source_path, target_path) #if file?(source_path)
36
+ assure_symlink(source_path, target_path)
37
37
  end
38
38
  end
39
39
  end
@@ -52,6 +52,14 @@ module Luban
52
52
  execute(:mkdir, '-p', *opts, path)
53
53
  end
54
54
 
55
+ def truncate(path)
56
+ execute(:cat, "/dev/null", ">", path)
57
+ end
58
+
59
+ def touch(path)
60
+ execute(:touch, path)
61
+ end
62
+
55
63
  def rm(*opts, path)
56
64
  execute(:rm, '-f', *opts, path)
57
65
  end
@@ -106,13 +114,10 @@ module Luban
106
114
 
107
115
  def url_exists?(url)
108
116
  # Sent HEAD request to avoid downloading the file contents
109
- test("curl -s -L -I -o /dev/null -f #{url}")
110
-
111
- # Other effective ways to check url existence with curl
112
-
117
+ test("curl -s -L -I -o /dev/null -f #{url}") or
113
118
  # In case HEAD request is refused,
114
119
  # only the first byte of the file is requested
115
- # test("curl -s -L -o /dev/null -f -r 0-0 #{url}")
120
+ test("curl -s -L -o /dev/null -f -r 0-0 #{url}")
116
121
 
117
122
  # Alternatively, http code (200) can be validated
118
123
  # capture("curl -s -L -I -o /dev/null -w '%{http_code}' #{url}") == '200'
@@ -0,0 +1,43 @@
1
+ module Luban
2
+ module Deployment
3
+ module Packages
4
+ class Logrotate < Luban::Deployment::Package::Base
5
+ apply_to :all do
6
+ before_install do
7
+ depend_on 'popt', version: '1.16'
8
+ end
9
+ end
10
+
11
+ class Installer < Luban::Deployment::Package::Installer
12
+ define_executable 'logrotate'
13
+
14
+ def source_repo
15
+ @source_repo ||= "https://github.com"
16
+ end
17
+
18
+ def source_url_root
19
+ @source_url_root ||= "logrotate/logrotate/releases/download/#{package_major_version}"
20
+ end
21
+
22
+ def installed?
23
+ return false unless file?(logrotate_executable)
24
+ pattern = "logrotate #{package_major_version}"
25
+ match?("#{logrotate_executable} --version 2>&1", pattern)
26
+ end
27
+
28
+ def bin_path
29
+ @bin_path ||= install_path.join('sbin')
30
+ end
31
+
32
+ protected
33
+
34
+ def configure_package!
35
+ with compose_build_env_variables do
36
+ test("./autogen.sh", ">> #{install_log_file_path} 2>&1") and super
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,38 @@
1
+ module Luban
2
+ module Deployment
3
+ module Packages
4
+ class Popt < Luban::Deployment::Package::Base
5
+ class Installer < Luban::Deployment::Package::Installer
6
+ def header_file
7
+ @header_file ||= include_path.join('popt.h')
8
+ end
9
+
10
+ def shared_obj_file
11
+ @shared_obj_file ||= lib_path.join("libpopt.#{lib_extension}")
12
+ end
13
+
14
+ def source_repo
15
+ @source_repo ||= "http://rpm5.org"
16
+ end
17
+
18
+ def source_url_root
19
+ @source_url_root ||= "files/popt"
20
+ end
21
+
22
+ def installed?
23
+ file?(header_file) and file?(shared_obj_file)
24
+ end
25
+
26
+ protected
27
+
28
+ def configure_build_options
29
+ super
30
+ @configure_opts.unshift("--disable-static")
31
+ end
32
+
33
+ def update_binstubs!; end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -46,14 +46,15 @@ module Luban
46
46
 
47
47
  apply_to '>= 1.9.3' do
48
48
  before_install do
49
- depend_on 'openssl', version: '1.0.2h'
49
+ depend_on 'openssl', version: '1.0.2j'
50
+ depend_on 'rubygems', version: '2.6.7'
50
51
  #depend_on 'yaml', version: '0.1.6'
51
52
  end
52
53
  end
53
54
 
54
55
  apply_to :all do
55
56
  after_install do
56
- depend_on 'bundler', version: '1.12.3'
57
+ depend_on 'bundler', version: '1.13.3'
57
58
  end
58
59
  end
59
60
 
@@ -72,7 +73,7 @@ module Luban
72
73
  provision_tasks[:install].switch :install_doc, "Install Ruby document"
73
74
  provision_tasks[:install].switch :install_tcl, "Install with Tcl"
74
75
  provision_tasks[:install].switch :install_tk, "Install with Tk"
75
- provision_tasks[:install].option :rubygems, "Rubygems version (effective for v1.9.2 or below)"
76
+ provision_tasks[:install].option :rubygems, "Rubygems version"
76
77
  provision_tasks[:install].option :bundler, "Bundler version"
77
78
  provision_tasks[:install].option :openssl, "OpenSSL version (effective for v1.9.3 or above)"
78
79
  end
@@ -33,7 +33,6 @@ module Luban
33
33
  end
34
34
 
35
35
  def source_repo
36
- #@source_repo ||= "http://production.cf.rubygems.org"
37
36
  @source_repo ||= "https://rubygems.org"
38
37
  end
39
38
 
@@ -119,7 +119,6 @@ module Luban
119
119
 
120
120
  parameter :application
121
121
  parameter :scm_role
122
- parameter :logrotate_files
123
122
 
124
123
  def env_name
125
124
  @env_name ||= "#{stage}.#{project}/#{application}"
@@ -137,8 +136,6 @@ module Luban
137
136
 
138
137
  def set_default_application_parameters
139
138
  set_default :scm_role, :scm
140
- set_default :logrotate_files, []
141
-
142
139
  setup_default_application_config_finder
143
140
  end
144
141
 
@@ -1,6 +1,3 @@
1
- <% unless has_cronjobs? -%>
2
- # !!! No cronjobs for <%= user %> !!!
3
- <% end -%>
4
1
  <% cronjobs.each do |cronjob| -%>
5
2
  <%= "#{crontab_entry(**cronjob)}" %>
6
3
  <% end -%>
@@ -1,5 +1,5 @@
1
1
  module Luban
2
2
  module Deployment
3
- VERSION = "0.8.10"
3
+ VERSION = "0.9.0"
4
4
  end
5
5
  end
@@ -21,13 +21,10 @@ module Luban
21
21
  @env_path ||= luban_root_path.join('env')
22
22
  end
23
23
 
24
- def etc_path
25
- @etc_path ||= luban_root_path.join('etc')
26
- end
27
-
28
- def logrotate_path
29
- @logrotate_path = etc_path.join('logrotate')
24
+ def archives_path
25
+ @archives_path ||= luban_root_path.join('archives')
30
26
  end
27
+ alias_method :local_archives_path, :archives_path
31
28
 
32
29
  def tmp_path
33
30
  @tmp_path ||= luban_root_path.join('tmp')
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.8.10
4
+ version: 0.9.0
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-09-29 00:00:00.000000000 Z
11
+ date: 2016-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: luban-cli
@@ -143,7 +143,9 @@ files:
143
143
  - lib/luban/deployment/helpers/utils.rb
144
144
  - lib/luban/deployment/packages/bundler.rb
145
145
  - lib/luban/deployment/packages/git.rb
146
+ - lib/luban/deployment/packages/logrotate.rb
146
147
  - lib/luban/deployment/packages/openssl.rb
148
+ - lib/luban/deployment/packages/popt.rb
147
149
  - lib/luban/deployment/packages/ruby.rb
148
150
  - lib/luban/deployment/packages/rubygems.rb
149
151
  - lib/luban/deployment/packages/yaml.rb
@@ -200,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
202
  version: '0'
201
203
  requirements: []
202
204
  rubyforge_project:
203
- rubygems_version: 2.5.1
205
+ rubygems_version: 2.6.7
204
206
  signing_key:
205
207
  specification_version: 4
206
208
  summary: Ruby framework for server automation and application deployment