luban 0.11.6 → 0.12.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/lib/luban/deployment/cli/application/base.rb +3 -3
- data/lib/luban/deployment/cli/application/constructor.rb +1 -0
- data/lib/luban/deployment/cli/application/docker/dockerable.rb +46 -0
- data/lib/luban/deployment/cli/application/docker/dockerizer.rb +277 -0
- data/lib/luban/deployment/cli/application/docker/templates/Dockerfile.erb +33 -0
- data/lib/luban/deployment/cli/application/docker/templates/docker-compose-env.erb +1 -0
- data/lib/luban/deployment/cli/application/docker/templates/docker-compose.yml.erb +9 -0
- data/lib/luban/deployment/cli/application/docker.rb +2 -0
- data/lib/luban/deployment/cli/application/publisher.rb +4 -16
- data/lib/luban/deployment/cli/application/repository.rb +1 -1
- data/lib/luban/deployment/cli/application/worker.rb +6 -1
- data/lib/luban/deployment/cli/application.rb +1 -1
- data/lib/luban/deployment/cli/command.rb +2 -2
- data/lib/luban/deployment/cli/package/base.rb +1 -1
- data/lib/luban/deployment/cli/package/installer/install.rb +11 -9
- data/lib/luban/deployment/cli/package/worker.rb +17 -4
- data/lib/luban/deployment/configuration/core.rb +2 -5
- data/lib/luban/deployment/helpers/configuration.rb +2 -2
- data/lib/luban/deployment/parameters.rb +44 -2
- data/lib/luban/deployment/runner.rb +3 -2
- data/lib/luban/deployment/templates/application/config/deploy/__stage.rb.erb +2 -0
- data/lib/luban/deployment/templates/application/config/deploy.rb.erb +4 -0
- data/lib/luban/deployment/templates/crontab_header.erb +0 -1
- data/lib/luban/deployment/templates/header.erb +0 -1
- data/lib/luban/deployment/templates/project/.gitignore +1 -1
- data/lib/luban/deployment/templates/project/Lubanfile.rb.erb +2 -1
- data/lib/luban/deployment/version.rb +1 -1
- data/lib/luban/deployment/worker/paths.rb +12 -13
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 410b9b5e5e7b9fbc389290fa45951741ad84dcb5
|
4
|
+
data.tar.gz: a55967147d22fb2d87b00b60cde50f9ff8bdd563
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d75e1599d8dd7d377cf5c3385d0b9e75e32338c45aa9190548696933dcc2f59c99ac7951afc7c78f8c3227e2205ea98d185b20fb9fe1320cacd38926fcaae03a
|
7
|
+
data.tar.gz: 1bc91fc605e99ad1c5ab5fa4a91f84e4e5b9499990870679e65d8c59fd749bc409feff9ea15f9819573869155abef20b76d07e34299f8ab64a14b81fc13856e3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## Version 0.12.1 (Feb 09, 2017)
|
4
|
+
|
5
|
+
Minor enhancements:
|
6
|
+
* Added build context in docker compose file template
|
7
|
+
* Used docker-compose to build application
|
8
|
+
|
9
|
+
## Version 0.12.0 (Feb 08, 2017)
|
10
|
+
|
11
|
+
New features
|
12
|
+
* Supported Docker deployment
|
13
|
+
* Handled docker options for remote connectivity properly
|
14
|
+
* Docker options could be set per stage config as well as per app server
|
15
|
+
|
16
|
+
Minor enhancements:
|
17
|
+
* Refactored common paths into module Luban::Deployment::Package::Worker::Base
|
18
|
+
* Defined root paths for docker, releases, packages and deployment projects
|
19
|
+
* Restructured symlinks for vendor/cache and vendor/bundle
|
20
|
+
* Deprecated deployment release log
|
21
|
+
* Minor bug fixes and code cleanup
|
22
|
+
|
23
|
+
## Version 0.11.6 (Feb 07, 2017)
|
24
|
+
|
25
|
+
Bug fixes:
|
26
|
+
* Corrected symlink creations for profiles when deploying releases
|
27
|
+
|
3
28
|
## Version 0.11.6 (Feb 07, 2017)
|
4
29
|
|
5
30
|
Bug fixes:
|
@@ -163,8 +163,8 @@ module Luban
|
|
163
163
|
|
164
164
|
def build(args:, opts:)
|
165
165
|
show_app_environment
|
166
|
-
install_all!(args: args, opts: opts)
|
167
166
|
build_repositories(args: args, opts: opts)
|
167
|
+
install_all!(args: args, opts: opts)
|
168
168
|
end
|
169
169
|
|
170
170
|
def destroy(args:, opts:)
|
@@ -357,7 +357,7 @@ module Luban
|
|
357
357
|
opts[:release][:tag] ||=
|
358
358
|
release_tag(args: {}, opts: opts.merge(repository: source.merge(version: version)))
|
359
359
|
end
|
360
|
-
dispatch_task :release_tag, to: :repository,
|
360
|
+
dispatch_task :release_tag, to: :repository, locally: true
|
361
361
|
|
362
362
|
def show_app_environment
|
363
363
|
puts "#{display_name} in #{parent.class.name}"
|
@@ -421,7 +421,7 @@ module Luban
|
|
421
421
|
dispatch_task :deploy_cronjobs!, to: :crontab, as: :deploy_cronjobs
|
422
422
|
|
423
423
|
def print_summary(result)
|
424
|
-
result.each do |entry|
|
424
|
+
Array(result).each do |entry|
|
425
425
|
s = entry[:summary]
|
426
426
|
puts " [#{entry[:hostname]}] #{s[:status]} #{s[:name]} (#{s[:published]})"
|
427
427
|
puts " [#{entry[:hostname]}] #{s[:alert]}" unless s[:alert].nil?
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Luban
|
2
|
+
module Deployment
|
3
|
+
class Application
|
4
|
+
module Dockerable
|
5
|
+
def self.prepended(base)
|
6
|
+
base.dispatch_task :init_docker!, to: :dockerizer, as: :init_docker, locally: true
|
7
|
+
base.dispatch_task :dockerize_application!, to: :dockerizer, as: :dockerize_application, locally: true
|
8
|
+
base.dispatch_task :build_application!, to: :dockerizer, as: :build_application, locally: true
|
9
|
+
base.dispatch_task :distribute_application!, to: :dockerizer, as: :distribute_application
|
10
|
+
end
|
11
|
+
|
12
|
+
def deploy(args:, opts:)
|
13
|
+
super
|
14
|
+
dockerize_application!(args: args, opts: opts)[:build].tap do |build|
|
15
|
+
build_application!(args: args, opts: opts.merge(build: build))
|
16
|
+
distribute_application!(args: args, opts: opts.merge(build: build))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def init_profiles(args:, opts:)
|
21
|
+
super
|
22
|
+
init_docker!(args: args,
|
23
|
+
opts: opts.merge(default_docker_templates_path: default_docker_templates_path,
|
24
|
+
docker_templates_path: config_finder[:application].templates_path))
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_docker_templates_path
|
28
|
+
@default_docker_template_path ||= base_templates_path(__FILE__)
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
%i(setup! install_all! uninstall_all! destroy!
|
34
|
+
binstubs! which! whence!
|
35
|
+
cleanup_packages! cleanup_application!
|
36
|
+
show_current_packages! show_summary_packages! get_summary
|
37
|
+
publish_release! deprecate_published_release!
|
38
|
+
deploy_profile!).each do |action|
|
39
|
+
define_method("#{action}") do |args:, opts:|
|
40
|
+
super(args: args, opts: opts.merge(locally: true))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,277 @@
|
|
1
|
+
module Luban
|
2
|
+
module Deployment
|
3
|
+
class Application
|
4
|
+
class Dockerizer < Worker
|
5
|
+
attr_reader :build
|
6
|
+
|
7
|
+
DefaultRevisionSize = 12
|
8
|
+
|
9
|
+
def docker_templates_path
|
10
|
+
task.opts.docker_templates_path
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_docker_templates_path
|
14
|
+
task.opts.default_docker_templates_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_docker_tcp_port; docker_tls_verify? ? "2376" : "2375"; end
|
18
|
+
|
19
|
+
def docker_tls_verify?;
|
20
|
+
host[:docker_tls_verify].nil? ? docker_tls_verify : host[:docker_tls_verify]
|
21
|
+
end
|
22
|
+
|
23
|
+
def docker_ca_cert_path; docker_cert_path.join("ca.pem"); end
|
24
|
+
def docker_client_cert_path; docker_cert_path.join("cert.pem"); end
|
25
|
+
def tls_key_path; docker_cert_path.join("key.pem"); end
|
26
|
+
|
27
|
+
def tls_options
|
28
|
+
["--tlsverify", "--tlscacert #{docker_ca_cert_path}",
|
29
|
+
"--tlscert #{docker_client_cert_path}", "--tlskey #{tls_key_path}"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def docker_host
|
33
|
+
unix_socket = host[:docker_unix_socket] || docker_unix_socket
|
34
|
+
if unix_socket.nil?
|
35
|
+
tcp_port = host[:docker_tcp_port] || docker_tcp_port || default_docker_tcp_port
|
36
|
+
"tcp://#{hostname}:#{tcp_port}"
|
37
|
+
else
|
38
|
+
"unix://#{unix_socket}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def docker_options
|
43
|
+
@docker_options ||= ["-H #{docker_host}"].concat(docker_tls_verify? ? tls_options : [])
|
44
|
+
end
|
45
|
+
|
46
|
+
def revision_size
|
47
|
+
task.opts.revision_size || DefaultRevisionSize
|
48
|
+
end
|
49
|
+
|
50
|
+
def init_docker
|
51
|
+
puts " Initializing #{application_name} docker profile"
|
52
|
+
docker_templates.each do |path|
|
53
|
+
print " - #{path}"
|
54
|
+
src_path = default_docker_templates_path.join(path)
|
55
|
+
dst_path = docker_templates_path.join(path)
|
56
|
+
if file?(dst_path)
|
57
|
+
puts " [skipped]"
|
58
|
+
else
|
59
|
+
upload!(src_path, dst_path)
|
60
|
+
puts " [created]"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def dockerize_application
|
66
|
+
rmdir(build[:path]) if force?
|
67
|
+
dockerize_application!
|
68
|
+
case build[:status]
|
69
|
+
when :succeeded
|
70
|
+
update_result "Successfully dockerized #{build[:image_tag]}."
|
71
|
+
when :skipped
|
72
|
+
update_result "Skipped! ALREADY dockerized #{build[:image_tag]}.", status: :skipped
|
73
|
+
else
|
74
|
+
update_result "FAILED to dockerize #{build[:image_tag]}.", status: :failed, level: :error
|
75
|
+
end
|
76
|
+
update_result build: build
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_image_id(docker_options = [])
|
80
|
+
capture(:docker, docker_options.join(' '), :images, "-q", build[:image_tag])
|
81
|
+
end
|
82
|
+
|
83
|
+
def built?
|
84
|
+
!(build[:image_id] = get_image_id).empty?
|
85
|
+
end
|
86
|
+
|
87
|
+
def build_application
|
88
|
+
if built?
|
89
|
+
update_result "Skipped! ALREADY built #{build[:image_tag]}.", status: :skipped
|
90
|
+
return
|
91
|
+
end
|
92
|
+
output = compose_application!
|
93
|
+
|
94
|
+
if built?
|
95
|
+
update_result "Successfully built #{build[:image_tag]}."
|
96
|
+
else
|
97
|
+
update_result "FAILED to build #{build[:image_tag]}: #{output}.",
|
98
|
+
status: :failed, level: :error
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def distributed?
|
103
|
+
build[:image_id] == get_image_id(docker_options)
|
104
|
+
end
|
105
|
+
|
106
|
+
def distribute_application
|
107
|
+
if distributed?
|
108
|
+
update_result "Skipped! ALREADY distributed #{build[:image_tag]}.", status: :skipped
|
109
|
+
return
|
110
|
+
end
|
111
|
+
output = distribute_application!
|
112
|
+
|
113
|
+
if distributed?
|
114
|
+
update_result "Successfully distributed #{build[:image_tag]}."
|
115
|
+
else
|
116
|
+
update_result "FAILED to distribute #{build[:image_tag]}: #{output}",
|
117
|
+
status: :failed, level: :error
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
protected
|
122
|
+
|
123
|
+
def init
|
124
|
+
super
|
125
|
+
@build = task.opts.build || init_build
|
126
|
+
end
|
127
|
+
|
128
|
+
def init_build
|
129
|
+
(@build = {}).tap do |b|
|
130
|
+
b[:path] = build_path
|
131
|
+
b[:context] = context_path
|
132
|
+
b[:dockerfile] = dockerfile
|
133
|
+
b[:compose_file] = compose_file
|
134
|
+
b[:compose_env_file] = compose_env_file
|
135
|
+
b[:sources] = init_build_sources
|
136
|
+
b[:archives] = init_build_archives
|
137
|
+
b[:revision] = compose_revision
|
138
|
+
b[:image_tag] = image_tag(b[:revision])
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def init_build_sources
|
143
|
+
sources = { packages: packages_path }
|
144
|
+
releases = get_releases(releases_path)
|
145
|
+
if (v = releases.delete(:vendor))
|
146
|
+
sources[:vendor] = v
|
147
|
+
end
|
148
|
+
sources.merge!(releases)
|
149
|
+
profile_path = releases_path.dirname.join('profile')
|
150
|
+
profile = directory?(profile_path) ? get_releases(profile_path) : {}
|
151
|
+
sources[stage.to_sym] = app_path
|
152
|
+
sources.merge!(profile)
|
153
|
+
sources.inject({}) do |srcs, (name, path)|
|
154
|
+
md5 = md5_for_dir(path)
|
155
|
+
srcs[name] = { path: path, md5: md5, tag: md5[0, revision_size] }
|
156
|
+
srcs
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def compose_revision
|
161
|
+
require 'digest/md5'
|
162
|
+
build[:sources].inject(revisions = '') { |r, (_, src)| r += src[:md5] }
|
163
|
+
Digest::MD5.hexdigest(revisions)[0, revision_size]
|
164
|
+
end
|
165
|
+
|
166
|
+
def init_build_archives
|
167
|
+
build[:sources].each_key.inject(build[:archives] = {}) do |archives, name|
|
168
|
+
archives[name] = { path: archive_file_path("#{name}-#{build[:sources][name][:tag]}") }
|
169
|
+
archives
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def archive_file_name(name)
|
174
|
+
"#{project}-#{application}-#{name}.#{archive_file_extname}"
|
175
|
+
end
|
176
|
+
|
177
|
+
def archive_file_extname; "tar.xz"; end
|
178
|
+
|
179
|
+
def archive_file_path(name)
|
180
|
+
build[:context].join(archive_file_name(name))
|
181
|
+
end
|
182
|
+
|
183
|
+
def build_path; docker_path.join("build-#{stage}-#{build_tag}"); end
|
184
|
+
def context_path; build_path.join('context'); end
|
185
|
+
def image_tag(revision); "#{project}-#{application}-#{stage}:#{build_tag}-#{revision}"; end
|
186
|
+
def dockerfile; build[:context].join("Dockerfile"); end
|
187
|
+
def compose_file; build[:path].join("docker-compose.yml"); end
|
188
|
+
def compose_env_file; build[:path].join(".env"); end
|
189
|
+
|
190
|
+
def get_releases(path)
|
191
|
+
capture(:ls, '-xtd', path.join('*')).split.
|
192
|
+
collect { |p| File.basename(p) }.
|
193
|
+
inject({}) { |r, t| r[t.to_sym] = path.join(t); r }
|
194
|
+
end
|
195
|
+
|
196
|
+
def dockerize_application!
|
197
|
+
assure_dirs(build[:context])
|
198
|
+
package_application!
|
199
|
+
render_dockerfile
|
200
|
+
render_compose_env_file
|
201
|
+
render_compose_file
|
202
|
+
build[:status] = status
|
203
|
+
end
|
204
|
+
|
205
|
+
def package_application!
|
206
|
+
build[:archives].each_pair do |name, archive|
|
207
|
+
source = build[:sources][name]
|
208
|
+
archive[:status] =
|
209
|
+
if file?(archive[:path]) and archive[:path].basename.to_s =~ /#{source[:tag]}/
|
210
|
+
:skipped
|
211
|
+
else
|
212
|
+
execute(:tar, "-cJf", archive[:path], source[:path]) ? :succeeded : :failed
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def render_dockerfile
|
218
|
+
upload_by_template(file_to_upload: build[:dockerfile],
|
219
|
+
template_file: find_template_file('Dockerfile.erb'),
|
220
|
+
auto_revision: true)
|
221
|
+
end
|
222
|
+
|
223
|
+
def render_compose_env_file
|
224
|
+
upload_by_template(file_to_upload: build[:compose_env_file],
|
225
|
+
template_file: find_template_file('docker-compose-env.erb'),
|
226
|
+
auto_revision: true)
|
227
|
+
end
|
228
|
+
|
229
|
+
def render_compose_file
|
230
|
+
upload_by_template(file_to_upload: build[:compose_file],
|
231
|
+
template_file: find_template_file('docker-compose.yml.erb'),
|
232
|
+
auto_revision: true)
|
233
|
+
end
|
234
|
+
|
235
|
+
def status
|
236
|
+
build[:archives].each_value.inject(:skipped) do |status, archive|
|
237
|
+
if archive[:status] == :failed
|
238
|
+
status = :failed; break
|
239
|
+
end
|
240
|
+
if archive[:status] == :succeeded
|
241
|
+
status = :succeeded
|
242
|
+
end
|
243
|
+
status
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def build_application!
|
248
|
+
within build[:context] do
|
249
|
+
capture(:docker, :build, "-t", build[:image_tag], ".", "2>&1")
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def compose_application!
|
254
|
+
within build[:path] { capture(:"docker-compose", :build, "2>&1") }
|
255
|
+
end
|
256
|
+
|
257
|
+
def distribute_application!
|
258
|
+
capture(:docker, :save, build[:image_tag], "|",
|
259
|
+
:docker, docker_options.join(' '), "load", "2>&1")
|
260
|
+
end
|
261
|
+
|
262
|
+
def remove_image!(docker_options = [], image_id)
|
263
|
+
execute(:docker, docker_options.join(' '), :rmi, image_id, "2>/dev/null")
|
264
|
+
end
|
265
|
+
|
266
|
+
def docker_templates(format: "erb")
|
267
|
+
@docker_templates ||=
|
268
|
+
if default_docker_templates_path.directory?
|
269
|
+
Dir.chdir(default_docker_templates_path) { Dir["**/*.#{format}"] }
|
270
|
+
else
|
271
|
+
[]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
FROM <%= base_image %>
|
2
|
+
MAINTAINER <%= author['name'] %> <%= author['email'].inspect %>
|
3
|
+
|
4
|
+
RUN adduser -ms /bin/bash <%= luban_user %> && \
|
5
|
+
mkdir <%= luban_root_path %> && \
|
6
|
+
chown -R <%= luban_user %>:<%= luban_user %> <%= luban_root_path %>
|
7
|
+
|
8
|
+
<% build[:archives].each_value do |archive| -%>
|
9
|
+
ADD <%= archive[:path].basename %> /
|
10
|
+
<% end -%>
|
11
|
+
|
12
|
+
RUN ln -sf /usr/share/zoneinfo/<%= timezone %> /etc/localtime && \
|
13
|
+
echo "source <%= envrc_file %>" >> /home/<%= luban_user %>/.bashrc
|
14
|
+
|
15
|
+
<% build[:archives].each_value do |archive| -%>
|
16
|
+
ADD <%= archive[:path].basename %> /
|
17
|
+
<% end -%>
|
18
|
+
|
19
|
+
LABEL luban.project="<%= project %>" \
|
20
|
+
luban.application="<%= project %>" \
|
21
|
+
luban.stage="<%= stage %>" \
|
22
|
+
<%- build[:sources].each_pair do |name, source| -%>
|
23
|
+
luban.<%= name %>_tag="<%= source[:tag] %>" \
|
24
|
+
<%- end -%>
|
25
|
+
luban.build_tag="<%= build_tag %>" \
|
26
|
+
luban.bulid_rev="<%= build[:revision] %>"
|
27
|
+
luban.luban_user="<%= luban_user %>" \
|
28
|
+
luban.luban_root_path="<%= luban_root_path %>"
|
29
|
+
|
30
|
+
USER <%= luban_user %>
|
31
|
+
WORKDIR /home/<%= luban_user %>
|
32
|
+
|
33
|
+
CMD ["/bin/bash"]
|
@@ -0,0 +1 @@
|
|
1
|
+
COMPOSE_PROJECT_NAME="<%= project %>"
|
@@ -25,20 +25,16 @@ module Luban
|
|
25
25
|
@releases_path ||= super.dirname.join(release_type)
|
26
26
|
end
|
27
27
|
|
28
|
-
def releases_log_path
|
29
|
-
@releases_log_path ||= app_path.join('releases.log')
|
30
|
-
end
|
31
|
-
|
32
28
|
def bundle_config_path
|
33
|
-
@bundle_config_path ||=
|
29
|
+
@bundle_config_path ||= releases_path.join('.bundle')
|
34
30
|
end
|
35
31
|
|
36
32
|
def bundle_path
|
37
|
-
@bundle_path ||=
|
33
|
+
@bundle_path ||= releases_path.join('vendor', 'bundle')
|
38
34
|
end
|
39
35
|
|
40
36
|
def gems_cache_path
|
41
|
-
@gems_cache_path ||=
|
37
|
+
@gems_cache_path ||= releases_path.join('vendor', 'cache')
|
42
38
|
end
|
43
39
|
|
44
40
|
def bundle_without
|
@@ -102,7 +98,6 @@ module Luban
|
|
102
98
|
test(:tar, "-xzf #{upload_to} -C #{releases_path}")
|
103
99
|
touch(release_path)
|
104
100
|
create_symlinks
|
105
|
-
update_releases_log
|
106
101
|
else
|
107
102
|
rmdir(release_path)
|
108
103
|
end
|
@@ -113,6 +108,7 @@ module Luban
|
|
113
108
|
def create_symlinks
|
114
109
|
send("create_#{release_type}_symlinks")
|
115
110
|
if has_gemfile?
|
111
|
+
create_linked_dirs(bundle_linked_dirs, from: releases_path, to: shared_path)
|
116
112
|
create_linked_dirs(bundle_linked_dirs, to: release_path)
|
117
113
|
end
|
118
114
|
end
|
@@ -141,14 +137,6 @@ module Luban
|
|
141
137
|
create_linked_files(to: release_path)
|
142
138
|
end
|
143
139
|
|
144
|
-
def update_releases_log
|
145
|
-
execute %{echo "[$(date -u)][#{user}] #{release_log_message}" >> #{releases_log_path}}
|
146
|
-
end
|
147
|
-
|
148
|
-
def release_log_message
|
149
|
-
"#{release_name} in #{stage} #{project} is published successfully."
|
150
|
-
end
|
151
|
-
|
152
140
|
def cleanup_releases(keep_releases = 1)
|
153
141
|
files = capture(:ls, '-xtd', releases_path.join("#{release_version}-*")).split(" ")
|
154
142
|
if files.count > keep_releases
|
@@ -214,7 +214,7 @@ module Luban
|
|
214
214
|
md5_file = gems_path.join("#{gem_file}.md5")
|
215
215
|
gems[gem_name] =
|
216
216
|
if file?(md5_file)
|
217
|
-
|
217
|
+
capture(:cat, md5_file)
|
218
218
|
else
|
219
219
|
md5_for(gem_file).tap { |md5| execute(:echo, "#{md5} > #{md5_file}") }
|
220
220
|
end
|
@@ -4,6 +4,7 @@ module Luban
|
|
4
4
|
class Worker < Luban::Deployment::Worker::Base
|
5
5
|
include Luban::Deployment::Worker::Paths::Remote
|
6
6
|
include Luban::Deployment::Service::Worker::Base
|
7
|
+
include Luban::Deployment::Package::Worker::Base
|
7
8
|
|
8
9
|
def gemfile
|
9
10
|
@gemfile ||= release_path.join('Gemfile')
|
@@ -19,12 +20,16 @@ module Luban
|
|
19
20
|
define_method("application_#{method}") { send("target_#{method}") }
|
20
21
|
end
|
21
22
|
|
23
|
+
def docker_path
|
24
|
+
@docker_path ||= docker_root_path.join(project, application)
|
25
|
+
end
|
26
|
+
|
22
27
|
def profile_name; 'app'; end
|
23
28
|
|
24
29
|
def release_tag; task.opts.release[:tag]; end
|
25
30
|
|
26
31
|
def releases_path
|
27
|
-
@releases_path ||=
|
32
|
+
@releases_path ||= releases_root_path.join(project, application, 'app')
|
28
33
|
end
|
29
34
|
|
30
35
|
def release_path
|
@@ -291,7 +291,7 @@ module Luban
|
|
291
291
|
|
292
292
|
def dispatch_task(task, to:, as: task, locally: false, &blk)
|
293
293
|
define_method(task) do |args:, opts:|
|
294
|
-
run_task(cmd: as, args: args, opts: opts, locally: locally,
|
294
|
+
run_task(cmd: as, args: args, opts: opts, locally: locally || opts[:locally],
|
295
295
|
worker_class: self.class.worker_class(to), &blk)
|
296
296
|
end
|
297
297
|
|
@@ -356,7 +356,7 @@ module Luban
|
|
356
356
|
|
357
357
|
def set_parameters
|
358
358
|
copy_parameters_from_parent(
|
359
|
-
:luban_roles, :luban_root_path, :work_dir, :apps_path,
|
359
|
+
:luban_roles, :luban_root_path, :work_dir, :apps_path, :author,
|
360
360
|
:stages, :applications, :user, :skip_promptless_authen
|
361
361
|
)
|
362
362
|
end
|
@@ -268,7 +268,7 @@ module Luban
|
|
268
268
|
end
|
269
269
|
|
270
270
|
def print_summary(result)
|
271
|
-
result.each do |entry|
|
271
|
+
Array(result).each do |entry|
|
272
272
|
s = entry[:summary]
|
273
273
|
puts " [#{entry[:hostname]}] #{s[:status]} #{s[:name]} (#{s[:installed]})"
|
274
274
|
puts " [#{entry[:hostname]}] #{s[:executable]}" unless s[:executable].nil?
|
@@ -157,19 +157,21 @@ module Luban
|
|
157
157
|
end
|
158
158
|
|
159
159
|
def which_current
|
160
|
-
get_summary
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
160
|
+
get_summary.tap do |result|
|
161
|
+
result.summary[:executable] = "Not found"
|
162
|
+
if current? and current_symlinked? and
|
163
|
+
file?(executable = File.join(readlink(current_path), 'bin', task.args.executable))
|
164
|
+
result.summary[:executable] = executable
|
165
|
+
end
|
165
166
|
end
|
166
167
|
end
|
167
168
|
|
168
169
|
def whence_origin
|
169
|
-
get_summary
|
170
|
-
|
171
|
-
|
172
|
-
|
170
|
+
get_summary.tap do |result|
|
171
|
+
result.summary[:executable] = "Not found"
|
172
|
+
if file?(executable = bin_path.join(task.args.executable))
|
173
|
+
result.summary[:executable] = executable
|
174
|
+
end
|
173
175
|
end
|
174
176
|
end
|
175
177
|
|
@@ -4,6 +4,23 @@ module Luban
|
|
4
4
|
class Worker < Luban::Deployment::Worker::Base
|
5
5
|
include Luban::Deployment::Worker::Paths::Remote
|
6
6
|
|
7
|
+
module Base
|
8
|
+
def packages_path
|
9
|
+
@packages_path ||= packages_root_path.join(project, application)
|
10
|
+
end
|
11
|
+
|
12
|
+
def package_install_path(package_name)
|
13
|
+
packages_path.join(package_name.to_s, 'versions',
|
14
|
+
packages[package_name.to_sym].current_version)
|
15
|
+
end
|
16
|
+
|
17
|
+
def package_bin_path(package_name)
|
18
|
+
package_install_path(package_name).join('bin')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
include Base
|
23
|
+
|
7
24
|
class << self
|
8
25
|
def package_class(package)
|
9
26
|
Luban::Deployment::Package::Base.package_class(package)
|
@@ -41,10 +58,6 @@ module Luban
|
|
41
58
|
@current_bin_path ||= current_path.join('bin')
|
42
59
|
end
|
43
60
|
|
44
|
-
def packages_path
|
45
|
-
@packages_path ||= super.join(project, application)
|
46
|
-
end
|
47
|
-
|
48
61
|
def package_path
|
49
62
|
@package_path ||= packages_path.join(package_name)
|
50
63
|
end
|
@@ -45,14 +45,11 @@ module Luban
|
|
45
45
|
if name == :all
|
46
46
|
raise ArgumentError, 'Reserved role name, :all, is NOT allowed to use.'
|
47
47
|
end
|
48
|
-
|
48
|
+
servers.add_hosts_for_role(name, hosts, properties)
|
49
49
|
end
|
50
50
|
|
51
51
|
def server(name, **properties)
|
52
|
-
|
53
|
-
if new_server
|
54
|
-
new_server.ssh_options = fetch(:ssh_options) || {}
|
55
|
-
end
|
52
|
+
servers.add_host(name, properties)
|
56
53
|
end
|
57
54
|
|
58
55
|
def ask(key=nil, default:, prompt: nil, echo: true)
|
@@ -25,11 +25,11 @@ module Luban
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def role(name, hosts, **properties)
|
28
|
-
config.role(name, hosts, properties)
|
28
|
+
config.role(name, hosts, properties.merge(local: dockerized?))
|
29
29
|
end
|
30
30
|
|
31
31
|
def server(name, **properties)
|
32
|
-
config.server(name, properties)
|
32
|
+
config.server(name, properties.merge(local: dockerized?))
|
33
33
|
end
|
34
34
|
|
35
35
|
def roles(*names)
|
@@ -26,6 +26,10 @@ module Luban
|
|
26
26
|
mod.extend(Base)
|
27
27
|
end
|
28
28
|
|
29
|
+
def current_user
|
30
|
+
ENV['USER'] || `whoami`.chomp
|
31
|
+
end
|
32
|
+
|
29
33
|
parameter :luban_roles, default: %i(app)
|
30
34
|
parameter :luban_root_path, default: DefaultLubanRootPath
|
31
35
|
|
@@ -36,7 +40,8 @@ module Luban
|
|
36
40
|
parameter :work_dir
|
37
41
|
parameter :apps_path
|
38
42
|
parameter :project
|
39
|
-
parameter :user, default:
|
43
|
+
parameter :user, default: -> { current_user }
|
44
|
+
parameter :author
|
40
45
|
parameter :config_finder, default: ->{ Hash.new }
|
41
46
|
|
42
47
|
parameter :skip_promptless_authen, default: false
|
@@ -44,7 +49,10 @@ module Luban
|
|
44
49
|
protected
|
45
50
|
|
46
51
|
def validate_for_user
|
47
|
-
if user
|
52
|
+
if user.nil?
|
53
|
+
abort "Abort! Please specify the user name: user 'user name'"
|
54
|
+
end
|
55
|
+
if user != current_user
|
48
56
|
abort "Aborted! Given deployment user (#{user.inspect}) is NOT the current user #{ENV['USER'].inspect}" +
|
49
57
|
"Please switch to the deployment user before any deployments."
|
50
58
|
end
|
@@ -107,8 +115,32 @@ module Luban
|
|
107
115
|
end
|
108
116
|
end
|
109
117
|
|
118
|
+
module Docker
|
119
|
+
extend Base
|
120
|
+
|
121
|
+
parameter :luban_user, default: 'luban'
|
122
|
+
parameter :build_tag, default: '0.0.0'
|
123
|
+
parameter :base_image, default: 'centos:7'
|
124
|
+
parameter :timezone, default: 'UTC'
|
125
|
+
parameter :docker_tls_verify, default: false
|
126
|
+
parameter :docker_cert_path
|
127
|
+
parameter :docker_tcp_port
|
128
|
+
parameter :docker_unix_socket
|
129
|
+
|
130
|
+
def validate_for_docker_cert_path
|
131
|
+
return if !docker_tls_verify and docker_cert_path.nil?
|
132
|
+
if docker_cert_path.is_a?(String)
|
133
|
+
docker_cert_path Pathname.new(docker_cert_path)
|
134
|
+
end
|
135
|
+
unless docker_cert_path.is_a?(Pathname)
|
136
|
+
abort "Aborted! Docker cert path should be a String or a Pathname: docker_cert_path 'path to docker certs'"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
110
141
|
module Application
|
111
142
|
extend Base
|
143
|
+
include Docker
|
112
144
|
|
113
145
|
DefaultLogrotateMaxAge = 7 # days
|
114
146
|
DefaultLogrotateInterval = 10 # mins
|
@@ -123,6 +155,16 @@ module Luban
|
|
123
155
|
@env_name ||= "#{stage}.#{project}/#{application}"
|
124
156
|
end
|
125
157
|
|
158
|
+
def dockerize
|
159
|
+
unless dockerized?
|
160
|
+
singleton_class.send(:prepend, Luban::Deployment::Application::Dockerable)
|
161
|
+
set :dockerized, true
|
162
|
+
skip_promptless_authen true
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def dockerized?; fetch :dockerized; end
|
167
|
+
|
126
168
|
def monitor_itself?
|
127
169
|
env_name == process_monitor[:env]
|
128
170
|
end
|
@@ -10,7 +10,8 @@ module Luban
|
|
10
10
|
def default_rc
|
11
11
|
@default_rc ||= { 'luban_roles' => %i(app),
|
12
12
|
'luban_root_path' => Parameters::General::DefaultLubanRootPath,
|
13
|
-
'stages' => %w(development staging production)
|
13
|
+
'stages' => %w(development staging production),
|
14
|
+
'author' => { 'name' => 'author name', 'email' => 'author@email.com' }
|
14
15
|
}
|
15
16
|
end
|
16
17
|
|
@@ -46,7 +47,7 @@ module Luban
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def set_default_common_parameters
|
49
|
-
%i(luban_roles luban_root_path stages).each { |p| set_default p, rc[p.to_s] }
|
50
|
+
%i(luban_roles luban_root_path stages author).each { |p| set_default p, rc[p.to_s] }
|
50
51
|
set_default :user, (rc['user'] || ENV['USER'])
|
51
52
|
end
|
52
53
|
|
@@ -17,8 +17,12 @@ module Luban
|
|
17
17
|
end
|
18
18
|
|
19
19
|
module Remote
|
20
|
-
def
|
21
|
-
@
|
20
|
+
def deployment_projects_path
|
21
|
+
@deployment_projects_path ||= luban_root_path.join('projects')
|
22
|
+
end
|
23
|
+
|
24
|
+
def releases_root_path
|
25
|
+
@releases_root_path ||= luban_root_path.join('releases')
|
22
26
|
end
|
23
27
|
|
24
28
|
def env_path
|
@@ -38,6 +42,10 @@ module Luban
|
|
38
42
|
@downloads_path ||= luban_root_path.join('downloads')
|
39
43
|
end
|
40
44
|
|
45
|
+
def docker_root_path
|
46
|
+
@docker_root_path ||= luban_root_path.join('docker')
|
47
|
+
end
|
48
|
+
|
41
49
|
def project_path
|
42
50
|
@project_path ||= env_path.join("#{stage}.#{project}")
|
43
51
|
end
|
@@ -70,17 +78,8 @@ module Luban
|
|
70
78
|
@unset_envrc_file ||= app_path.join(".unset_envrc")
|
71
79
|
end
|
72
80
|
|
73
|
-
def
|
74
|
-
@
|
75
|
-
end
|
76
|
-
|
77
|
-
def package_install_path(package_name)
|
78
|
-
packages_path.join(project, application, package_name.to_s, 'versions',
|
79
|
-
packages[package_name.to_sym].current_version)
|
80
|
-
end
|
81
|
-
|
82
|
-
def package_bin_path(package_name)
|
83
|
-
package_install_path(package_name).join('bin')
|
81
|
+
def packages_root_path
|
82
|
+
@packages_root_path ||= luban_root_path.join('packages')
|
84
83
|
end
|
85
84
|
|
86
85
|
def app_archives_path
|
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.
|
4
|
+
version: 0.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rubyist Lei
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
11
|
+
date: 2017-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: luban-cli
|
@@ -107,6 +107,12 @@ files:
|
|
107
107
|
- lib/luban/deployment/cli/application/constructor.rb
|
108
108
|
- lib/luban/deployment/cli/application/controller.rb
|
109
109
|
- lib/luban/deployment/cli/application/crontab.rb
|
110
|
+
- lib/luban/deployment/cli/application/docker.rb
|
111
|
+
- lib/luban/deployment/cli/application/docker/dockerable.rb
|
112
|
+
- lib/luban/deployment/cli/application/docker/dockerizer.rb
|
113
|
+
- lib/luban/deployment/cli/application/docker/templates/Dockerfile.erb
|
114
|
+
- lib/luban/deployment/cli/application/docker/templates/docker-compose-env.erb
|
115
|
+
- lib/luban/deployment/cli/application/docker/templates/docker-compose.yml.erb
|
110
116
|
- lib/luban/deployment/cli/application/publisher.rb
|
111
117
|
- lib/luban/deployment/cli/application/repository.rb
|
112
118
|
- lib/luban/deployment/cli/application/scm/git.rb
|