luban 0.11.6 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|