dapp 0.2.8 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/config/en/common.yml +3 -1
- data/config/en/net_status.yml +5 -2
- data/lib/dapp.rb +9 -6
- data/lib/dapp/application.rb +30 -5
- data/lib/dapp/application/logging.rb +2 -2
- data/lib/dapp/application/path.rb +10 -6
- data/lib/dapp/build/stage/base.rb +77 -9
- data/lib/dapp/build/stage/chef_cookbooks.rb +1 -1
- data/lib/dapp/build/stage/from.rb +2 -1
- data/lib/dapp/build/stage/infra_install.rb +1 -1
- data/lib/dapp/build/stage/source_1.rb +1 -1
- data/lib/dapp/build/stage/source_1_archive.rb +0 -4
- data/lib/dapp/build/stage/source_2.rb +1 -1
- data/lib/dapp/build/stage/source_3.rb +1 -1
- data/lib/dapp/build/stage/source_base.rb +3 -3
- data/lib/dapp/builder/chef.rb +160 -140
- data/lib/dapp/cli.rb +2 -1
- data/lib/dapp/cli/base.rb +1 -1
- data/lib/dapp/cli/build.rb +7 -7
- data/lib/dapp/cli/flush.rb +3 -3
- data/lib/dapp/cli/flush/{build_cache.rb → metadata.rb} +7 -7
- data/lib/dapp/cli/flush/{stage_cache.rb → stages.rb} +4 -4
- data/lib/dapp/cli/push.rb +3 -3
- data/lib/dapp/cli/run.rb +59 -0
- data/lib/dapp/config/application.rb +20 -2
- data/lib/dapp/config/artifact.rb +69 -0
- data/lib/dapp/config/chef.rb +27 -0
- data/lib/dapp/config/docker.rb +1 -1
- data/lib/dapp/config/git_artifact.rb +3 -29
- data/lib/dapp/config/shell.rb +20 -0
- data/lib/dapp/controller.rb +21 -22
- data/lib/dapp/exception/base.rb +1 -5
- data/lib/dapp/filelock.rb +1 -1
- data/lib/dapp/git_artifact.rb +2 -2
- data/lib/dapp/git_repo/base.rb +5 -5
- data/lib/dapp/git_repo/own.rb +6 -2
- data/lib/dapp/git_repo/remote.rb +5 -3
- data/lib/dapp/helper/cli.rb +7 -1
- data/lib/dapp/helper/log.rb +2 -2
- data/lib/dapp/helper/shellout.rb +1 -1
- data/lib/dapp/helper/trivia.rb +0 -4
- data/lib/dapp/image/arguments.rb +115 -0
- data/lib/dapp/image/docker.rb +76 -0
- data/lib/dapp/image/stage.rb +74 -0
- data/lib/dapp/version.rb +1 -1
- metadata +9 -6
- data/lib/dapp/docker_image.rb +0 -51
- data/lib/dapp/stage_image.rb +0 -160
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NTM1NTkwNWNjMzM0YTkzYTdlOGMzODY4MzE4ZGQ5YWZmNjI0YmU5Zg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YjM5ODYyYzIzNDA3YjkyODFkYThjYjE2NTFhNDA4MGQxM2IyZGE2Mg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OThjNmU0YmUyODZlODdkNzI2YjdiM2MyZDA4YmZkOWY2NTdmM2Y4MGJkYWM1
|
10
|
+
MTliMzkyMjcwMThiMGMzNTE2MGQyMGI0NGMyMTNlMDdkM2M5NDMzYjcxZTc0
|
11
|
+
YzM3YmMzZTkyNGYwZTM4YmJjMjY5YmFkN2U3YmVmMTgwODA5ZWY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OWRiZGIzNzY0MTQzYzk3OTJlMDYxNDA4ZjI2OWEwZGQzNDQ2NTQ3NjQ4MGUx
|
14
|
+
N2Y4NTVmY2UyNTNhMGUzNmUwMTI1Zjg3ODJjZDhlYmIwZDIyZDgxZTFiZmRm
|
15
|
+
YWUwNGU0ZmY1MzJlNmU2ZDNhYmRmYTg1ZWFmODU1ZTYxMWFjZDQ=
|
data/config/en/common.yml
CHANGED
@@ -5,10 +5,12 @@ en:
|
|
5
5
|
info: "date: %{date}\nsize: %{size} MB"
|
6
6
|
commands: "commands:"
|
7
7
|
process:
|
8
|
+
artifact_copy: "copying artifact '%{name}'"
|
8
9
|
git_artifact_loading: 'loading git_artifact'
|
10
|
+
git_artifact_clone: "cloning remote git_artifact '%{name}'"
|
11
|
+
git_artifact_fetch: "fetching remote git_artifact '%{name}'"
|
9
12
|
chefdk_loading: 'loading chefdk'
|
10
13
|
berks_vendor: 'berks_vendor'
|
11
|
-
git_artifact_fetch: "fetching remote git_artifact '%{name}'"
|
12
14
|
status:
|
13
15
|
process:
|
14
16
|
pushing: '[PUSHING]'
|
data/config/en/net_status.yml
CHANGED
@@ -5,6 +5,7 @@ en:
|
|
5
5
|
shell_command_failed: ">>> START STREAM\n%{stream}\n>>> END STREAM"
|
6
6
|
application:
|
7
7
|
application_not_built: "Application hasn't been built yet!"
|
8
|
+
application_not_run: "Application run failed!"
|
8
9
|
git_branch_without_name: "Application has specific revision that isn't associated with a branch name!"
|
9
10
|
ci_environment_required: 'CI environment required (Travis or GitLab CI)!'
|
10
11
|
build:
|
@@ -14,11 +15,13 @@ en:
|
|
14
15
|
another_image_already_tagged: 'Image with other id already tagged!'
|
15
16
|
built_id_not_defined: '`from.built_id` not defined!'
|
16
17
|
controller:
|
17
|
-
|
18
|
+
push_command_unexpected_apps_number: "Push command can process only one application!"
|
19
|
+
run_command_unexpected_apps_number: "Run command can process only one application!"
|
18
20
|
no_such_app: "No such app: '%{patterns}' in '%{path}'!"
|
19
21
|
dappfile_not_found: "Dappfile not found!"
|
20
22
|
config:
|
21
23
|
builder_type_conflict: 'Conflict between builder types!'
|
22
24
|
builder_type_unsupported: "Defined unsupported builder type `%{type}`!"
|
23
25
|
docker_from_not_defined: "Docker `from` not defined!"
|
24
|
-
|
26
|
+
artifact_unexpected_attribute: "Artifact doesn't have attribute '%{attr}'!"
|
27
|
+
git_artifact_unexpected_attribute: "'%{type}' git artifact doesn't have attribute '%{attr}'!"
|
data/lib/dapp.rb
CHANGED
@@ -32,13 +32,15 @@ require 'dapp/cli/push'
|
|
32
32
|
require 'dapp/cli/smartpush'
|
33
33
|
require 'dapp/cli/list'
|
34
34
|
require 'dapp/cli/flush'
|
35
|
-
require 'dapp/cli/flush/
|
36
|
-
require 'dapp/cli/flush/
|
35
|
+
require 'dapp/cli/flush/stages'
|
36
|
+
require 'dapp/cli/flush/metadata'
|
37
|
+
require 'dapp/cli/run'
|
37
38
|
require 'dapp/filelock'
|
38
39
|
require 'dapp/config/application'
|
39
40
|
require 'dapp/config/main'
|
40
41
|
require 'dapp/config/chef'
|
41
42
|
require 'dapp/config/shell'
|
43
|
+
require 'dapp/config/artifact'
|
42
44
|
require 'dapp/config/git_artifact'
|
43
45
|
require 'dapp/config/docker'
|
44
46
|
require 'dapp/builder/base'
|
@@ -66,20 +68,21 @@ require 'dapp/application/logging'
|
|
66
68
|
require 'dapp/application/path'
|
67
69
|
require 'dapp/application/tags'
|
68
70
|
require 'dapp/application'
|
69
|
-
require 'dapp/
|
70
|
-
require 'dapp/
|
71
|
+
require 'dapp/image/arguments'
|
72
|
+
require 'dapp/image/docker'
|
73
|
+
require 'dapp/image/stage'
|
71
74
|
require 'dapp/git_repo/base'
|
72
75
|
require 'dapp/git_repo/own'
|
73
76
|
require 'dapp/git_repo/remote'
|
74
77
|
require 'dapp/git_artifact'
|
75
|
-
require 'dapp/exception/base'
|
76
|
-
require 'dapp/exception/introspect_image'
|
77
78
|
require 'dapp/error/base'
|
78
79
|
require 'dapp/error/application'
|
79
80
|
require 'dapp/error/build'
|
80
81
|
require 'dapp/error/config'
|
81
82
|
require 'dapp/error/controller'
|
82
83
|
require 'dapp/error/shellout'
|
84
|
+
require 'dapp/exception/base'
|
85
|
+
require 'dapp/exception/introspect_image'
|
83
86
|
|
84
87
|
# Dapp
|
85
88
|
module Dapp
|
data/lib/dapp/application.rb
CHANGED
@@ -14,21 +14,28 @@ module Dapp
|
|
14
14
|
attr_reader :config
|
15
15
|
attr_reader :cli_options
|
16
16
|
attr_reader :ignore_git_fetch
|
17
|
+
attr_reader :is_artifact
|
17
18
|
|
18
|
-
def initialize(config:, cli_options:, ignore_git_fetch: false)
|
19
|
+
def initialize(config:, cli_options:, ignore_git_fetch: false, is_artifact: false)
|
19
20
|
@config = config
|
20
21
|
@cli_options = cli_options
|
21
22
|
|
22
|
-
@
|
23
|
-
@
|
23
|
+
@tmp_path = Dir.mktmpdir(cli_options[:tmp_dir_prefix] || 'dapp-')
|
24
|
+
@metadata_path = cli_options[:metadata_dir] || home_path('.dapps-metadata')
|
24
25
|
|
25
26
|
@last_stage = Build::Stage::Source5.new(self)
|
26
27
|
@ignore_git_fetch = ignore_git_fetch
|
28
|
+
@is_artifact = is_artifact
|
27
29
|
end
|
28
30
|
|
29
31
|
def build!
|
30
|
-
|
31
|
-
|
32
|
+
log_step(config._name)
|
33
|
+
with_log_indent do
|
34
|
+
last_stage.build!
|
35
|
+
last_stage.save_in_cache!
|
36
|
+
end
|
37
|
+
ensure
|
38
|
+
FileUtils.rm_rf(tmp_path)
|
32
39
|
end
|
33
40
|
|
34
41
|
def export!(repo)
|
@@ -46,10 +53,28 @@ module Dapp
|
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
56
|
+
def run(docker_options, command)
|
57
|
+
raise Error::Application, code: :application_not_built unless last_stage.image.tagged?
|
58
|
+
cmd = "docker run #{[docker_options, last_stage.image.name, command].flatten.compact.join(' ')}"
|
59
|
+
if dry_run?
|
60
|
+
log_info(cmd)
|
61
|
+
else
|
62
|
+
system(cmd) || raise(Error::Application, code: :application_not_run)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def signature
|
67
|
+
last_stage.send(:signature)
|
68
|
+
end
|
69
|
+
|
49
70
|
def builder
|
50
71
|
@builder ||= Builder.const_get(config._builder.capitalize).new(self)
|
51
72
|
end
|
52
73
|
|
74
|
+
def meta_options
|
75
|
+
{ cli_options: cli_options, ignore_git_fetch: ignore_git_fetch }
|
76
|
+
end
|
77
|
+
|
53
78
|
protected
|
54
79
|
|
55
80
|
attr_reader :last_stage
|
@@ -58,8 +58,8 @@ module Dapp
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
def log_secondary_process(message, **
|
62
|
-
log_process(message, **
|
61
|
+
def log_secondary_process(message, **kwargs, &blk)
|
62
|
+
log_process(message, **kwargs.merge(style: { message: :secondary, success: :secondary }), &blk)
|
63
63
|
end
|
64
64
|
|
65
65
|
def log_process_verbose(message, process:, style: {}, &blk)
|
@@ -7,16 +7,20 @@ module Dapp
|
|
7
7
|
make_path(config._home_path, *path).expand_path
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
make_path(@
|
10
|
+
def tmp_path(*path)
|
11
|
+
make_path(@tmp_path, *path).expand_path.tap { |p| FileUtils.mkdir_p p.parent }
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
make_path(@
|
14
|
+
def metadata_path(*path)
|
15
|
+
make_path(@metadata_path, home_path.basename, *path).expand_path.tap { |p| FileUtils.mkdir_p p.parent }
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
make_path('/.
|
18
|
+
def container_dapp_path(*path)
|
19
|
+
make_path('/.dapp', *path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def container_tmp_path(*path)
|
23
|
+
container_dapp_path('tmp', *path)
|
20
24
|
end
|
21
25
|
|
22
26
|
private
|
@@ -46,14 +46,16 @@ module Dapp
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def signature
|
49
|
-
hashsum prev_stage.signature
|
49
|
+
hashsum [prev_stage.signature, artifacts_signatures]
|
50
50
|
end
|
51
51
|
|
52
52
|
def image
|
53
53
|
@image ||= begin
|
54
|
-
|
55
|
-
image.add_volume "#{application.
|
54
|
+
Image::Stage.new(name: image_name, from: from_image).tap do |image|
|
55
|
+
image.add_volume "#{application.tmp_path}:#{application.container_tmp_path}"
|
56
|
+
before_artifacts.each { |artifact| apply_artifact(artifact, image) }
|
56
57
|
yield image if block_given?
|
58
|
+
after_artifacts.each { |artifact| apply_artifact(artifact, image) }
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
@@ -73,7 +75,7 @@ module Dapp
|
|
73
75
|
end
|
74
76
|
|
75
77
|
def should_be_introspected?
|
76
|
-
application.cli_options[:introspect_stage] == name && !application.dry_run?
|
78
|
+
application.cli_options[:introspect_stage] == name && !application.dry_run? && !application.is_artifact
|
77
79
|
end
|
78
80
|
|
79
81
|
def image_build!
|
@@ -94,14 +96,14 @@ module Dapp
|
|
94
96
|
end
|
95
97
|
|
96
98
|
def image_info
|
97
|
-
date,
|
98
|
-
_date,
|
99
|
-
[date, (
|
99
|
+
date, size = image.info
|
100
|
+
_date, from_size = from_image.info
|
101
|
+
[date, (from_size.to_f - size.to_f).abs]
|
100
102
|
end
|
101
103
|
|
102
104
|
def format_image_info
|
103
|
-
date,
|
104
|
-
application.t(code: 'image.info', data: { date: Time.parse(date).localtime, size:
|
105
|
+
date, size = image_info
|
106
|
+
application.t(code: 'image.info', data: { date: Time.parse(date).localtime, size: size.to_f.round(2) })
|
105
107
|
end
|
106
108
|
|
107
109
|
# rubocop:disable Metrics/AbcSize
|
@@ -115,6 +117,72 @@ module Dapp
|
|
115
117
|
end
|
116
118
|
end if application.log? && application.log_verbose?
|
117
119
|
end
|
120
|
+
# rubocop:enable Metrics/AbcSize
|
121
|
+
|
122
|
+
def before_artifacts
|
123
|
+
@before_artifacts ||= do_artifacts(application.config._artifact.select { |artifact| artifact._before == name })
|
124
|
+
end
|
125
|
+
|
126
|
+
def after_artifacts
|
127
|
+
@after_artifacts ||= do_artifacts(application.config._artifact.select { |artifact| artifact._after == name })
|
128
|
+
end
|
129
|
+
|
130
|
+
def do_artifacts(artifacts)
|
131
|
+
artifacts.map do |artifact|
|
132
|
+
{
|
133
|
+
name: artifact._config._name,
|
134
|
+
options: artifact._artifact_options,
|
135
|
+
app: Application.new(config: artifact._config, is_artifact: true, **application.meta_options).tap(&:build!)
|
136
|
+
}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def artifacts_signatures
|
141
|
+
(before_artifacts + after_artifacts).map { |artifact| hashsum [artifact[:app].signature, artifact[:options]] }
|
142
|
+
end
|
143
|
+
|
144
|
+
def apply_artifact(artifact, image)
|
145
|
+
return if application.dry_run?
|
146
|
+
|
147
|
+
artifact_name = artifact[:name]
|
148
|
+
app = artifact[:app]
|
149
|
+
cwd = artifact[:options][:cwd]
|
150
|
+
paths = artifact[:options][:paths]
|
151
|
+
owner = artifact[:options][:owner]
|
152
|
+
group = artifact[:options][:group]
|
153
|
+
where_to_add = artifact[:options][:where_to_add]
|
154
|
+
|
155
|
+
docker_options = ['--rm',
|
156
|
+
"--volume #{application.tmp_path('artifact', artifact_name)}:#{app.container_tmp_path(artifact_name)}",
|
157
|
+
'--entrypoint /bin/sh']
|
158
|
+
commands = safe_cp(where_to_add, app.container_tmp_path(artifact_name), Process.uid, Process.gid)
|
159
|
+
application.log_secondary_process(application.t(code: 'process.artifact_copy', data: { name: artifact_name }), short: true) do
|
160
|
+
app.run(docker_options, Array(application.shellout_pack(commands)))
|
161
|
+
end
|
162
|
+
|
163
|
+
commands = safe_cp(application.container_tmp_path('artifact', artifact_name), where_to_add, owner, group, cwd, paths)
|
164
|
+
image.add_commands commands
|
165
|
+
end
|
166
|
+
|
167
|
+
# rubocop:disable Metrics/ParameterLists
|
168
|
+
def safe_cp(from, to, owner, group, cwd = '', paths = [])
|
169
|
+
credentials = ''
|
170
|
+
credentials += "-o #{owner} " if owner
|
171
|
+
credentials += "-g #{group} " if group
|
172
|
+
|
173
|
+
commands = []
|
174
|
+
commands << ['install', credentials, '-d', to].join(' ')
|
175
|
+
|
176
|
+
copy_files = lambda do |from_, cwd_, path_ = ''|
|
177
|
+
"find #{File.join(from_, cwd_, path_)} -type f -exec bash -ec 'install -D #{credentials} {} " \
|
178
|
+
"#{File.join(to, "$(echo {} | sed -e \"s/#{File.join(from_, cwd_).gsub('/', '\\/')}//g\")")}' \\;"
|
179
|
+
end
|
180
|
+
|
181
|
+
commands.concat(paths.empty? ? Array(copy_files.call(from, cwd)) : paths.map { |path| copy_files.call(from, cwd, path) })
|
182
|
+
commands << "find #{to} -type d -exec bash -ec 'install -d #{credentials} {}' \\;"
|
183
|
+
commands.join(' && ')
|
184
|
+
end
|
185
|
+
# rubocop:enable Metrics/ParameterLists
|
118
186
|
end # Base
|
119
187
|
end # Stage
|
120
188
|
end # Build
|
@@ -5,6 +5,7 @@ module Dapp
|
|
5
5
|
class From < Base
|
6
6
|
def signature
|
7
7
|
hashsum [from_image_name,
|
8
|
+
artifacts_signatures,
|
8
9
|
application.config._docker._from_cache_version,
|
9
10
|
Dapp::BUILD_CACHE_VERSION]
|
10
11
|
end
|
@@ -28,7 +29,7 @@ module Dapp
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def from_image
|
31
|
-
@from_image ||=
|
32
|
+
@from_image ||= Image::Stage.new(name: from_image_name)
|
32
33
|
end
|
33
34
|
|
34
35
|
def image_info
|
@@ -29,7 +29,7 @@ module Dapp
|
|
29
29
|
bash_commands = []
|
30
30
|
volumes = []
|
31
31
|
application.git_artifacts.each do |git_artifact|
|
32
|
-
volumes << "#{git_artifact.repo.
|
32
|
+
volumes << "#{git_artifact.repo.path}:#{git_artifact.repo.container_path}"
|
33
33
|
bash_commands.concat(git_artifact.send(apply_command_method, self))
|
34
34
|
end
|
35
35
|
|
@@ -43,7 +43,7 @@ module Dapp
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def dependencies_checksum
|
46
|
-
hashsum [prev_stage.signature]
|
46
|
+
hashsum [prev_stage.signature, artifacts_signatures]
|
47
47
|
end
|
48
48
|
|
49
49
|
def layer_commit(git_artifact)
|
@@ -94,7 +94,7 @@ module Dapp
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def layer_commit_file_path(git_artifact)
|
97
|
-
application.
|
97
|
+
application.metadata_path git_artifact.filename ".#{name}.#{git_artifact.paramshash}.#{dependencies_checksum}.commit"
|
98
98
|
end
|
99
99
|
|
100
100
|
def dependency_files_checksum(regs)
|
data/lib/dapp/builder/chef.rb
CHANGED
@@ -2,34 +2,23 @@ module Dapp
|
|
2
2
|
module Builder
|
3
3
|
# Chef
|
4
4
|
class Chef < Base
|
5
|
-
|
5
|
+
LOCAL_COOKBOOK_CHECKSUM_PATTERNS = %w(
|
6
6
|
recipes/**/*
|
7
7
|
files/**/*
|
8
8
|
templates/**/*
|
9
9
|
).freeze
|
10
10
|
|
11
|
-
STAGE_LOCAL_COOKBOOK_PATTERNS = %w(
|
12
|
-
metadata.json
|
13
|
-
recipes/%{stage}.rb
|
14
|
-
recipes/*_%{stage}.rb
|
15
|
-
files/default/%{stage}/*
|
16
|
-
templates/default/%{stage}/*
|
17
|
-
).freeze
|
18
|
-
|
19
11
|
DEFAULT_CHEFDK_IMAGE = 'dappdeps/chefdk:0.17.3-1'.freeze # TODO: config, DSL, DEFAULT_CHEFDK_IMAGE
|
20
12
|
|
21
13
|
[:infra_install, :infra_setup, :app_install, :app_setup].each do |stage|
|
22
14
|
define_method(:"#{stage}_checksum") { stage_cookbooks_checksum(stage) }
|
23
15
|
|
24
16
|
define_method(:"#{stage}") do |image|
|
25
|
-
install_stage_cookbooks(stage)
|
26
|
-
install_chef_solo_stage_config(stage)
|
27
|
-
|
28
17
|
unless stage_empty?(stage)
|
29
18
|
image.add_volumes_from(chefdk_container)
|
30
19
|
image.add_commands 'export PATH=/.dapp/deps/chefdk/bin:$PATH'
|
31
20
|
|
32
|
-
image.add_volume "#{
|
21
|
+
image.add_volume "#{stage_tmp_path(stage)}:#{container_stage_tmp_path(stage)}"
|
33
22
|
image.add_commands ['chef-solo',
|
34
23
|
"-c #{container_stage_config_path(stage)}",
|
35
24
|
"-o #{stage_cookbooks_runlist(stage).join(',')}"].join(' ')
|
@@ -42,9 +31,11 @@ module Dapp
|
|
42
31
|
end
|
43
32
|
|
44
33
|
def chef_cookbooks(image)
|
34
|
+
image.add_volume "#{cookbooks_vendor_path}:#{application.container_dapp_path('chef_vendored_cookbooks')}"
|
45
35
|
image.add_commands(
|
46
|
-
|
47
|
-
"cp -a #{
|
36
|
+
'mkdir -p /usr/share/dapp/chef_repo',
|
37
|
+
["cp -a #{application.container_dapp_path('chef_vendored_cookbooks')} ",
|
38
|
+
'/usr/share/dapp/chef_repo/cookbooks'].join
|
48
39
|
)
|
49
40
|
end
|
50
41
|
|
@@ -74,76 +65,40 @@ module Dapp
|
|
74
65
|
@cookbook_metadata ||= CookbookMetadata.new(cookbook_metadata_path)
|
75
66
|
end
|
76
67
|
|
68
|
+
|
77
69
|
def berksfile_lock_checksum
|
78
70
|
application.hashsum berksfile_lock_path.read if berksfile_lock_path.exist?
|
79
71
|
end
|
80
72
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
"#{name}::#{entrypoint}"
|
89
|
-
end
|
90
|
-
|
91
|
-
res.concat(application.config._chef._modules.map do |name|
|
92
|
-
to_runlist_entrypoint[name, stage]
|
93
|
-
end.compact)
|
94
|
-
|
95
|
-
project_main_entry = to_runlist_entrypoint[project_name, stage]
|
96
|
-
res << project_main_entry if project_main_entry
|
97
|
-
|
98
|
-
res.concat(application.config._app_runlist.map do |app_component|
|
99
|
-
to_runlist_entrypoint[project_name, [app_component, stage].join('_')]
|
100
|
-
end.compact)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
# rubocop:enable Metrics/AbcSize
|
104
|
-
|
105
|
-
def local_cookbook_paths
|
106
|
-
@local_cookbook_paths ||= berksfile.local_cookbooks
|
107
|
-
.values
|
108
|
-
.map { |cookbook| cookbook[:path] }
|
109
|
-
.product(LOCAL_COOKBOOK_PATTERNS)
|
110
|
-
.map { |cb, dir| Dir[cb.join(dir)] }
|
111
|
-
.flatten
|
112
|
-
.map(&Pathname.method(:new))
|
113
|
-
end
|
114
|
-
|
115
|
-
def stage_cookbooks_vendored_paths(stage, with_files: false)
|
116
|
-
Dir[cookbooks_vendor_path('*')]
|
117
|
-
.map do |cookbook_path|
|
118
|
-
if ['mdapp-*', project_name].any? { |pattern| File.fnmatch(pattern, File.basename(cookbook_path)) }
|
119
|
-
STAGE_LOCAL_COOKBOOK_PATTERNS.map do |pattern|
|
120
|
-
Dir[File.join(cookbook_path, pattern % { stage: stage })]
|
121
|
-
end
|
122
|
-
elsif with_files
|
123
|
-
Dir[File.join(cookbook_path, '**/*')]
|
124
|
-
else
|
125
|
-
cookbook_path
|
126
|
-
end
|
127
|
-
end
|
73
|
+
def local_cookbook_paths_for_checksum
|
74
|
+
@local_cookbook_paths_for_checksum ||= berksfile
|
75
|
+
.local_cookbooks
|
76
|
+
.values
|
77
|
+
.map { |cookbook| cookbook[:path] }
|
78
|
+
.product(LOCAL_COOKBOOK_CHECKSUM_PATTERNS)
|
79
|
+
.map { |cb, dir| Dir[cb.join(dir)] }
|
128
80
|
.flatten
|
129
81
|
.map(&Pathname.method(:new))
|
130
82
|
end
|
131
83
|
|
84
|
+
def stage_cookbooks_paths_for_checksum(stage)
|
85
|
+
install_stage_cookbooks(stage)
|
86
|
+
Dir[stage_cookbooks_path(stage, '**/*')].map(&Pathname.method(:new))
|
87
|
+
end
|
88
|
+
|
132
89
|
def stage_cookbooks_checksum_path(stage)
|
133
|
-
application.
|
90
|
+
application.metadata_path("#{cookbooks_checksum}.#{stage}.checksum")
|
134
91
|
end
|
135
92
|
|
136
93
|
def stage_cookbooks_checksum(stage)
|
137
94
|
if stage_cookbooks_checksum_path(stage).exist?
|
138
95
|
stage_cookbooks_checksum_path(stage).read.strip
|
139
96
|
else
|
140
|
-
|
141
|
-
|
142
|
-
if stage == :chef_cookbooks
|
143
|
-
checksum = cookbooks_checksum
|
97
|
+
checksum = if stage == :chef_cookbooks
|
98
|
+
cookbooks_checksum
|
144
99
|
else
|
145
|
-
|
146
|
-
_paths_checksum(
|
100
|
+
application.hashsum [
|
101
|
+
_paths_checksum(stage_cookbooks_paths_for_checksum(stage)),
|
147
102
|
*application.config._chef._modules,
|
148
103
|
stage == :infra_install ? chefdk_image : nil
|
149
104
|
].compact
|
@@ -157,11 +112,12 @@ module Dapp
|
|
157
112
|
def cookbooks_checksum
|
158
113
|
@cookbooks_checksum ||= application.hashsum [
|
159
114
|
berksfile_lock_checksum,
|
160
|
-
_paths_checksum(
|
115
|
+
_paths_checksum(local_cookbook_paths_for_checksum),
|
161
116
|
*application.config._chef._modules
|
162
117
|
]
|
163
118
|
end
|
164
119
|
|
120
|
+
|
165
121
|
def chefdk_image
|
166
122
|
DEFAULT_CHEFDK_IMAGE # TODO: config, DSL, DEFAULT_CHEFDK_IMAGE
|
167
123
|
end
|
@@ -187,101 +143,165 @@ module Dapp
|
|
187
143
|
end
|
188
144
|
end
|
189
145
|
|
146
|
+
|
190
147
|
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
191
148
|
def install_cookbooks
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
true
|
230
|
-
end
|
149
|
+
volumes_from = chefdk_container
|
150
|
+
application.log_secondary_process(application.t(code: 'process.berks_vendor')) do
|
151
|
+
ssh_auth_socket_path = nil
|
152
|
+
ssh_auth_socket_path = Pathname.new(ENV['SSH_AUTH_SOCK']).expand_path if ENV['SSH_AUTH_SOCK'] && File.exist?(ENV['SSH_AUTH_SOCK'])
|
153
|
+
|
154
|
+
vendor_commands = [
|
155
|
+
'mkdir -p ~/.ssh',
|
156
|
+
'echo "Host *" >> ~/.ssh/config',
|
157
|
+
'echo " StrictHostKeyChecking no" >> ~/.ssh/config',
|
158
|
+
'if [ ! -f Berksfile.lock ] ; then echo "Berksfile.lock not found" 1>&2 ; exit 1 ; fi',
|
159
|
+
'cp -a Berksfile.lock /tmp/Berksfile.lock.orig',
|
160
|
+
'/.dapp/deps/chefdk/bin/berks vendor /tmp/vendored_cookbooks',
|
161
|
+
'export LOCKDIFF=$(diff -u0 Berksfile.lock /tmp/Berksfile.lock.orig)',
|
162
|
+
['if [ "$LOCKDIFF" != "" ] ; then ',
|
163
|
+
'cp -a /tmp/Berksfile.lock.orig Berksfile.lock ; ',
|
164
|
+
'echo -e "Bad Berksfile.lock\n$LOCKDIFF" 1>&2 ; exit 1 ; fi'].join,
|
165
|
+
["find /tmp/vendored_cookbooks -type f -exec bash -ec '",
|
166
|
+
"install -D -o #{Process.uid} -g #{Process.gid} --mode $(stat -c %a {}) {} ",
|
167
|
+
"#{_cookbooks_vendor_path}/$(echo {} | sed -e \"s/\\/tmp\\/vendored_cookbooks\\///g\")' \\;"].join
|
168
|
+
]
|
169
|
+
|
170
|
+
application.shellout!(
|
171
|
+
['docker run --rm',
|
172
|
+
("--volume #{ssh_auth_socket_path}:#{ssh_auth_socket_path}" if ssh_auth_socket_path),
|
173
|
+
"--volume #{_cookbooks_vendor_path.tap(&:mkpath)}:#{_cookbooks_vendor_path}",
|
174
|
+
*berksfile.local_cookbooks
|
175
|
+
.values
|
176
|
+
.map { |cookbook| "--volume #{cookbook[:path]}:#{cookbook[:path]}" },
|
177
|
+
"--volumes-from #{volumes_from}",
|
178
|
+
"--workdir #{berksfile_path.parent}",
|
179
|
+
("--env SSH_AUTH_SOCK=#{ssh_auth_socket_path}" if ssh_auth_socket_path),
|
180
|
+
"dappdeps/berksdeps:0.1.0 bash #{application.shellout_pack(vendor_commands.join(' && '))}"].compact.join(' '),
|
181
|
+
log_verbose: application.log_verbose?
|
182
|
+
)
|
183
|
+
|
184
|
+
true
|
231
185
|
end
|
232
186
|
end
|
233
187
|
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
234
188
|
|
235
|
-
def
|
236
|
-
|
237
|
-
stage_cookbooks_vendored_paths(stage).each do |path|
|
238
|
-
new_path = stage_cookbooks_path(stage, path.relative_path_from(cookbooks_vendor_path))
|
239
|
-
new_path.parent.mkpath
|
240
|
-
FileUtils.cp_r path, new_path
|
241
|
-
end
|
189
|
+
def _cookbooks_vendor_path
|
190
|
+
application.metadata_path("cookbooks.#{cookbooks_checksum}")
|
242
191
|
end
|
243
192
|
|
244
|
-
def
|
245
|
-
|
193
|
+
def cookbooks_vendor_path(*path)
|
194
|
+
_cookbooks_vendor_path.tap do |cookbooks_path|
|
195
|
+
install_cookbooks unless cookbooks_path.exist?
|
196
|
+
end.join(*path)
|
246
197
|
end
|
247
198
|
|
248
|
-
def install_chef_solo_stage_config(stage)
|
249
|
-
stage_config_path(stage).write [
|
250
|
-
"file_cache_path \"/var/cache/dapp/chef\"\n",
|
251
|
-
"cookbook_path \"#{container_stage_cookbooks_path(stage)}\"\n"
|
252
|
-
].join
|
253
|
-
end
|
254
199
|
|
255
|
-
|
256
|
-
|
257
|
-
|
200
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
201
|
+
def install_stage_cookbooks(stage)
|
202
|
+
@install_stage_cookbooks ||= {}
|
203
|
+
@install_stage_cookbooks[stage] ||= true.tap do
|
204
|
+
common_paths = proc do |cookbook_path|
|
205
|
+
[['metadata.json', 'metadata.json'],
|
206
|
+
["files/#{stage}", 'files/default'],
|
207
|
+
["templates/#{stage}", 'templates/default']
|
208
|
+
].select { |from, _| cookbook_path.join(from).exist? }
|
209
|
+
end
|
258
210
|
|
259
|
-
|
260
|
-
|
211
|
+
install_paths = Dir[cookbooks_vendor_path('*')]
|
212
|
+
.map(&Pathname.method(:new))
|
213
|
+
.map { |cookbook_path|
|
214
|
+
cookbook_name = File.basename cookbook_path
|
215
|
+
is_project = (cookbook_name == project_name)
|
216
|
+
is_mdapp = cookbook_name.start_with? 'mdapp-'
|
217
|
+
mdapp_enabled = is_mdapp && application.config._chef._modules.include?(cookbook_name)
|
218
|
+
|
219
|
+
paths = if is_project
|
220
|
+
recipe_paths = application.config._chef._recipes
|
221
|
+
.map { |recipe| ["recipes/#{stage}/#{recipe}.rb", "recipes/#{recipe}.rb"] }
|
222
|
+
.select { |from, _| cookbook_path.join(from).exist? }
|
223
|
+
|
224
|
+
(recipe_paths + common_paths[cookbook_path]) if recipe_paths.any?
|
225
|
+
elsif is_mdapp and mdapp_enabled
|
226
|
+
recipe_path = "recipes/#{stage}.rb"
|
227
|
+
if cookbook_path.join(recipe_path).exist?
|
228
|
+
[[recipe_path, recipe_path]] + common_paths[cookbook_path]
|
229
|
+
end
|
230
|
+
else
|
231
|
+
[['.', '.']]
|
232
|
+
end
|
233
|
+
|
234
|
+
[cookbook_path, paths] if paths and paths.any?
|
235
|
+
}
|
236
|
+
.compact
|
237
|
+
|
238
|
+
stage_cookbooks_path(stage).mkpath
|
239
|
+
install_paths.each do |cookbook_path, paths|
|
240
|
+
paths.each do |from, to|
|
241
|
+
from_path = cookbook_path.join(from)
|
242
|
+
to_path = stage_cookbooks_path(stage, cookbook_path.basename, to)
|
243
|
+
to_path.parent.mkpath
|
244
|
+
FileUtils.cp_r from_path, to_path
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
261
248
|
end
|
249
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
250
|
+
|
251
|
+
# rubocop:disable Metrics/AbcSize
|
252
|
+
def stage_cookbooks_runlist(stage)
|
253
|
+
install_stage_cookbooks(stage)
|
254
|
+
|
255
|
+
@stage_cookbooks_runlist ||= {}
|
256
|
+
@stage_cookbooks_runlist[stage] ||= [].tap do |res|
|
257
|
+
to_runlist_entrypoint = proc do |cookbook, entrypoint|
|
258
|
+
entrypoint_file = stage_cookbooks_path(stage, cookbook, 'recipes', "#{entrypoint}.rb")
|
259
|
+
next unless entrypoint_file.exist?
|
260
|
+
"#{cookbook}::#{entrypoint}"
|
261
|
+
end
|
262
|
+
|
263
|
+
res.concat(application.config._chef._recipes.map do |recipe|
|
264
|
+
to_runlist_entrypoint[project_name, recipe]
|
265
|
+
end.flatten.compact)
|
262
266
|
|
263
|
-
|
264
|
-
|
267
|
+
res.concat(application.config._chef._modules.map do |mod|
|
268
|
+
to_runlist_entrypoint[mod, stage]
|
269
|
+
end.flatten.compact)
|
270
|
+
end
|
265
271
|
end
|
272
|
+
# rubocop:enable Metrics/AbcSize
|
266
273
|
|
267
|
-
def
|
268
|
-
|
274
|
+
def stage_empty?(stage)
|
275
|
+
stage_cookbooks_runlist(stage).empty?
|
269
276
|
end
|
270
277
|
|
271
278
|
def stage_cookbooks_path(stage, *path)
|
272
|
-
|
279
|
+
stage_tmp_path(stage, 'cookbooks', *path)
|
273
280
|
end
|
274
281
|
|
275
|
-
def container_stage_cookbooks_path(stage, *path)
|
276
|
-
container_stage_build_path(stage, 'cookbooks', *path)
|
277
|
-
end
|
278
282
|
|
279
|
-
def
|
280
|
-
|
283
|
+
def install_chef_solo_stage_config(stage)
|
284
|
+
@install_chef_solo_stage_config ||= {}
|
285
|
+
@install_chef_solo_stage_config[stage] ||= true.tap do
|
286
|
+
stage_tmp_path(stage, 'config.rb').write [
|
287
|
+
"file_cache_path \"/var/cache/dapp/chef\"\n",
|
288
|
+
"cookbook_path \"#{container_stage_tmp_path(stage, 'cookbooks')}\"\n"
|
289
|
+
].join
|
290
|
+
end
|
281
291
|
end
|
282
292
|
|
283
293
|
def container_stage_config_path(stage, *path)
|
284
|
-
|
294
|
+
install_chef_solo_stage_config(stage)
|
295
|
+
container_stage_tmp_path(stage, 'config.rb', *path)
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
def stage_tmp_path(stage, *path)
|
300
|
+
application.tmp_path(application.config._name, stage).join(*path)
|
301
|
+
end
|
302
|
+
|
303
|
+
def container_stage_tmp_path(_stage, *path)
|
304
|
+
path.compact.map(&:to_s).inject(Pathname.new('/chef_build'), &:+)
|
285
305
|
end
|
286
306
|
|
287
307
|
def _paths_checksum(paths)
|