dapp 0.7.36 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/config/en/common.yml +1 -3
  3. data/config/en/net_status.yml +7 -9
  4. data/lib/dapp.rb +3 -1
  5. data/lib/dapp/artifact.rb +7 -2
  6. data/lib/dapp/build/stage/after_setup_artifact.rb +1 -1
  7. data/lib/dapp/build/stage/artifact_base.rb +1 -1
  8. data/lib/dapp/build/stage/artifact_default.rb +24 -43
  9. data/lib/dapp/build/stage/base.rb +35 -31
  10. data/lib/dapp/build/stage/build_artifact.rb +1 -1
  11. data/lib/dapp/build/stage/from.rb +1 -1
  12. data/lib/dapp/build/stage/ga_archive_dependencies.rb +10 -1
  13. data/lib/dapp/build/stage/ga_artifact_patch.rb +2 -2
  14. data/lib/dapp/build/stage/ga_base.rb +18 -5
  15. data/lib/dapp/build/stage/ga_dependencies_base.rb +1 -1
  16. data/lib/dapp/build/stage/ga_latest_patch.rb +10 -2
  17. data/lib/dapp/build/stage/import_artifact.rb +1 -1
  18. data/lib/dapp/build/stage/install/ga_pre_install_patch_dependencies.rb +0 -4
  19. data/lib/dapp/build/stage/install/install.rb +1 -1
  20. data/lib/dapp/build/stage/mod/logging.rb +2 -2
  21. data/lib/dapp/build/stage/setup/ga_post_setup_patch.rb +0 -4
  22. data/lib/dapp/build/stage/setup/ga_post_setup_patch_dependencies.rb +2 -2
  23. data/lib/dapp/build/stage/setup/ga_pre_setup_patch.rb +0 -4
  24. data/lib/dapp/build/stage/setup/setup.rb +1 -1
  25. data/lib/dapp/builder/base.rb +0 -7
  26. data/lib/dapp/builder/chef.rb +67 -408
  27. data/lib/dapp/builder/chef/berksfile.rb +78 -69
  28. data/lib/dapp/builder/chef/cookbook.rb +257 -0
  29. data/lib/dapp/builder/chef/cookbook_metadata.rb +54 -52
  30. data/lib/dapp/builder/none.rb +0 -6
  31. data/lib/dapp/cli/build.rb +8 -1
  32. data/lib/dapp/cli/stage_image.rb +1 -1
  33. data/lib/dapp/config/directive/base.rb +1 -3
  34. data/lib/dapp/config/directive/git_artifact_remote.rb +3 -6
  35. data/lib/dapp/dimg.rb +13 -14
  36. data/lib/dapp/dimg/path.rb +1 -9
  37. data/lib/dapp/error/tar_writer.rb +6 -0
  38. data/lib/dapp/git_artifact.rb +136 -37
  39. data/lib/dapp/git_repo/base.rb +44 -28
  40. data/lib/dapp/git_repo/own.rb +11 -7
  41. data/lib/dapp/git_repo/remote.rb +8 -45
  42. data/lib/dapp/image/docker.rb +9 -11
  43. data/lib/dapp/image/stage.rb +1 -1
  44. data/lib/dapp/project/chef.rb +2 -7
  45. data/lib/dapp/project/command/stages/cleanup_local.rb +1 -2
  46. data/lib/dapp/project/command/stages/cleanup_repo.rb +1 -2
  47. data/lib/dapp/version.rb +2 -2
  48. metadata +4 -3
  49. data/lib/dapp/build/stage/setup/chef_cookbooks.rb +0 -36
@@ -1,69 +1,78 @@
1
- module Dapp
2
- module Builder
3
- class Chef < Base
4
- # Berksfile
5
- class Berksfile
6
- # Parser
7
- class Parser
8
- def initialize(berksfile)
9
- @berksfile = berksfile
10
- parse
11
- end
12
-
13
- def cookbook(name, *_args, path: nil, **_kwargs)
14
- @berksfile.add_local_cookbook_path(name, path) if path
15
- end
16
-
17
- # rubocop:disable Style/MethodMissing
18
- def method_missing(*_a, &_blk)
19
- end
20
- # rubocop:enable Style/MethodMissing
21
-
22
- private
23
-
24
- def parse
25
- instance_eval(@berksfile.path.read, @berksfile.path.to_s)
26
- end
27
- end # Parser
28
-
29
- attr_reader :home_path
30
- attr_reader :path
31
- attr_reader :local_cookbooks
32
-
33
- def initialize(home_path, path)
34
- @home_path = home_path
35
- @path = path
36
- @local_cookbooks = {}
37
- @parser = Parser.new(self)
38
- end
39
-
40
- def add_local_cookbook_path(name, path)
41
- raise(::Dapp::Builder::Chef::Error, code: :berksfile_absolute_path_forbidden,
42
- data: { cookbook: name, path: path }) if path.start_with? '/'
43
-
44
- desc = {
45
- name: name,
46
- path: home_path.join(path),
47
- chefignore: [],
48
- }
49
-
50
- if desc[:path].join('chefignore').exist?
51
- chefignore_patterns = desc[:path].join('chefignore').read.split("\n").map(&:strip)
52
- desc[:chefignore] = Dir[*chefignore_patterns.map {|pattern| desc[:path].join(pattern)}]
53
- .map(&Pathname.method(:new))
54
- end
55
-
56
- @local_cookbooks[name] = desc
57
- end
58
-
59
- def local_cookbook?(name)
60
- local_cookbooks.key? name
61
- end
62
-
63
- def local_cookbook(name)
64
- local_cookbooks[name]
65
- end
66
- end # Berksfile
67
- end # Chef
68
- end # Builder
69
- end # Dapp
1
+ module Dapp::Builder
2
+ class Chef::Berksfile
3
+ class << self
4
+ def from_file(cookbook_path, berksfile_file_path)
5
+ berksfile = self.new(cookbook_path)
6
+ FileParser.new(berksfile_file_path, berksfile)
7
+ berksfile
8
+ end
9
+
10
+ def from_conf(cookbook_path, conf)
11
+ # TODO
12
+ end
13
+ end # << self
14
+
15
+ class FileParser
16
+ def initialize(berksfile_file_path, berksfile)
17
+ @berksfile_file_path = berksfile_file_path
18
+ @berksfile = berksfile
19
+
20
+ parse
21
+ end
22
+
23
+ def cookbook(name, *_args, path: nil, **_kwargs)
24
+ @berksfile.add_local_cookbook_path(name, path) if path
25
+ end
26
+
27
+ # rubocop:disable Style/MethodMissing
28
+ def method_missing(*_a, &_blk)
29
+ end
30
+ # rubocop:enable Style/MethodMissing
31
+
32
+ private
33
+
34
+ def parse
35
+ instance_eval(@berksfile_file_path.read, @berksfile_file_path.to_s)
36
+ end
37
+ end # FileParser
38
+
39
+ attr_reader :cookbook_path
40
+ attr_reader :local_cookbooks
41
+
42
+ def initialize(cookbook_path)
43
+ @cookbook_path = Pathname.new(cookbook_path)
44
+ @local_cookbooks = {}
45
+ end
46
+
47
+ def dump
48
+ #FIXME
49
+ end
50
+
51
+ def add_local_cookbook_path(name, path)
52
+ raise(::Dapp::Builder::Chef::Error, code: :berksfile_absolute_path_forbidden,
53
+ data: { cookbook: name, path: path }) if path.start_with? '/'
54
+
55
+ desc = {
56
+ name: name,
57
+ path: cookbook_path.join(path),
58
+ chefignore: [],
59
+ }
60
+
61
+ if desc[:path].join('chefignore').exist?
62
+ chefignore_patterns = desc[:path].join('chefignore').read.split("\n").map(&:strip)
63
+ desc[:chefignore] = Dir[*chefignore_patterns.map {|pattern| desc[:path].join(pattern)}]
64
+ .map(&Pathname.method(:new))
65
+ end
66
+
67
+ @local_cookbooks[name] = desc
68
+ end
69
+
70
+ def local_cookbook?(name)
71
+ local_cookbooks.key? name
72
+ end
73
+
74
+ def local_cookbook(name)
75
+ local_cookbooks[name]
76
+ end
77
+ end # Chef::Berksfile
78
+ end # Dapp::Builder
@@ -0,0 +1,257 @@
1
+ module Dapp::Builder
2
+ # Локальный cookbook сборщик с правилами
3
+ # сборки dimg образов для chef сборщика.
4
+ class Chef::Cookbook
5
+ CHECKSUM_PATTERNS = %w(
6
+ attributes/**/*
7
+ recipes/**/*
8
+ files/**/*
9
+ templates/**/*
10
+ ).freeze
11
+
12
+ attr_reader :builder
13
+
14
+ attr_reader :path
15
+ attr_reader :vendor_path
16
+ attr_reader :berksfile
17
+ attr_reader :metadata
18
+ attr_reader :enabled_recipes
19
+ attr_reader :enabled_modules
20
+
21
+ def initialize(builder, path:, berksfile:, metadata:, enabled_recipes:, enabled_modules:)
22
+ @builder = builder
23
+ @path = Pathname.new(path)
24
+ @berksfile = berksfile
25
+ @metadata = metadata
26
+ @enabled_recipes = enabled_recipes
27
+ @enabled_modules = enabled_modules
28
+ end
29
+
30
+ def name
31
+ metadata.name
32
+ end
33
+
34
+ def local_paths
35
+ @local_paths ||= [].tap do |paths|
36
+ paths << path
37
+ paths.push *berksfile.local_cookbooks.values.map {|cookbook| cookbook[:path]}
38
+ paths.uniq!
39
+ end
40
+ end
41
+
42
+ # TODO Сookbook'и зависимости на локальной файловой системе
43
+ # TODO должны обрабатываться рекурсивно. Чтобы контрольная сумма
44
+ # TODO учитывала все зависимости всех зависимых локальных cookbook'ов.
45
+ def checksum
46
+ @checksum ||= begin
47
+ all_local_paths = local_paths
48
+ .product(CHECKSUM_PATTERNS)
49
+ .map {|cb, dir| Dir[cb.join(dir)]}
50
+ .flatten
51
+ .map(&Pathname.method(:new))
52
+
53
+ builder.dimg.hashsum [
54
+ builder.dimg.paths_content_hashsum(all_local_paths),
55
+ *all_local_paths.map {|p| p.relative_path_from(self.path).to_s}.sort
56
+ ].compact
57
+ end
58
+ end
59
+
60
+ def vendor_path
61
+ builder.dimg.project.lock(_vendor_lock_name, default_timeout: 120) do
62
+ vendor! unless _vendor_path.join('.created_at').exist?
63
+ end
64
+ _vendor_path
65
+ end
66
+
67
+ def vendor!
68
+ volumes_from = [builder.dimg.project.base_container, builder.chefdk_container]
69
+
70
+ builder.dimg.project.log_secondary_process(builder.dimg.project.t(code: _vendor_process_name)) do
71
+ volumes_from = [builder.dimg.project.base_container, builder.chefdk_container]
72
+
73
+ vendor_commands = [
74
+ "#{builder.dimg.project.mkdir_bin} -p ~/.ssh",
75
+ "echo \"Host *\" >> ~/.ssh/config",
76
+ "echo \" StrictHostKeyChecking no\" >> ~/.ssh/config",
77
+ *local_paths.map {|path| "#{builder.dimg.project.rsync_bin} --archive --relative #{path} /tmp/local_cookbooks"},
78
+ "cd /tmp/local_cookbooks/#{path}",
79
+ '/.dapp/deps/chefdk/bin/berks vendor /tmp/cookbooks',
80
+ ["#{builder.dimg.project.find_bin} /tmp/cookbooks -type d -exec #{builder.dimg.project.bash_bin} -ec '",
81
+ "#{builder.dimg.project.install_bin} -o #{Process.uid} -g #{Process.gid} --mode $(#{builder.dimg.project.stat_bin} -c %a {}) -d ",
82
+ "#{_vendor_path}/$(echo {} | #{builder.dimg.project.sed_bin} -e \"s/^\\/tmp\\/cookbooks//\")' \\;"].join,
83
+ ["#{builder.dimg.project.find_bin} /tmp/cookbooks -type f -exec #{builder.dimg.project.bash_bin} -ec '",
84
+ "#{builder.dimg.project.install_bin} -o #{Process.uid} -g #{Process.gid} --mode $(#{builder.dimg.project.stat_bin} -c %a {}) {} ",
85
+ "#{_vendor_path}/$(echo {} | #{builder.dimg.project.sed_bin} -e \"s/\\/tmp\\/cookbooks//\")' \\;"].join,
86
+ "#{builder.dimg.project.install_bin} -o #{Process.uid} -g #{Process.gid} --mode 0644 <(#{builder.dimg.project.date_bin} +%s.%N) #{_vendor_path.join('.created_at')}"
87
+ ]
88
+
89
+ builder.dimg.project.shellout!(
90
+ ['docker run --rm',
91
+ volumes_from.map {|container| "--volumes-from #{container}"}.join(' '),
92
+ *local_paths.map {|path| "--volume #{path}:#{path}"},
93
+ ("--volume #{builder.dimg.project.ssh_auth_sock}:/tmp/dapp-ssh-agent" if builder.dimg.project.ssh_auth_sock),
94
+ "--volume #{_vendor_path.tap(&:mkpath)}:#{_vendor_path}",
95
+ ('--env SSH_AUTH_SOCK=/tmp/dapp-ssh-agent' if builder.dimg.project.ssh_auth_sock),
96
+ "dappdeps/berksdeps:0.1.0 #{builder.dimg.project.bash_bin} -ec '#{builder.dimg.project.shellout_pack(vendor_commands.join(' && '))}'"].compact.join(' '),
97
+ log_verbose: builder.dimg.project.log_verbose?
98
+ )
99
+ end
100
+ end
101
+
102
+ def stage_cookbooks_path(stage)
103
+ _stage_cookbooks_path(stage).tap do |_cookbooks_path|
104
+ @stage_cookbooks_installed ||= {}
105
+ @stage_cookbooks_installed[stage] ||= true.tap {install_stage_cookbooks(stage)}
106
+ end
107
+ end
108
+
109
+ def stage_enabled_modules(stage)
110
+ @stage_enabled_modules ||= {}
111
+ @stage_enabled_modules[stage] ||= enabled_modules.select {|cookbook| stage_entry_exist?(stage, cookbook, stage)}
112
+ end
113
+
114
+ def stage_enabled_recipes(stage)
115
+ @stage_enabled_recipes ||= {}
116
+ @stage_enabled_recipes[stage] ||= enabled_recipes.select {|recipe| stage_entry_exist?(stage, self.name, recipe)}
117
+ end
118
+
119
+ def stage_checksum(stage)
120
+ paths = Dir[stage_cookbooks_path(stage).join('**/*')].map(&Pathname.method(:new))
121
+
122
+ builder.dimg.hashsum [
123
+ builder.dimg.paths_content_hashsum(paths),
124
+ *paths.map {|p| p.relative_path_from(stage_cookbooks_path(stage)).to_s}.sort,
125
+ stage == :before_install ? builder.chefdk_image : nil
126
+ ].compact
127
+ end
128
+
129
+ protected
130
+
131
+ def _vendor_path
132
+ builder.dimg.build_path.join('cookbooks', checksum)
133
+ end
134
+
135
+ def _vendor_process_name
136
+ "process.vendoring_builder_cookbooks"
137
+ end
138
+
139
+ def _vendor_lock_name
140
+ "#{builder.dimg.project.name}.cookbooks.#{checksum}"
141
+ end
142
+
143
+ def stage_entry_exist?(stage, cookbook, entrypoint)
144
+ stage_cookbooks_path(stage).join(cookbook, 'recipes', "#{entrypoint}.rb").exist?
145
+ end
146
+
147
+ def install_stage_cookbooks(stage)
148
+ _stage_cookbooks_path(stage).mkpath
149
+
150
+ stage_install_paths(stage).each do |cookbook_path, paths|
151
+ cookbook = cookbook_path.basename.to_s
152
+
153
+ paths.each do |from, to|
154
+ if from.nil?
155
+ to_path = _stage_cookbooks_path(stage).join(cookbook, 'recipes/void.rb')
156
+ to_path.parent.mkpath
157
+ FileUtils.touch to_path
158
+ else
159
+ from_path = cookbook_path.join(from)
160
+ to_path = _stage_cookbooks_path(stage).join(cookbook, to)
161
+ if from_path.directory? && to_path.exist?
162
+ Dir[from_path.join('**/*')]
163
+ .map(&Pathname.method(:new))
164
+ .each do |from_subpath|
165
+ to_subpath = to_path.join(from_subpath.relative_path_from(from_path))
166
+ raise(::Dapp::Builder::Chef::Error,
167
+ code: :stage_path_overlap,
168
+ data: { stage: stage,
169
+ cookbook: cookbook,
170
+ from: from_subpath.relative_path_from(cookbook_path),
171
+ to: to_subpath.relative_path_from(_stage_cookbooks_path(stage).join(cookbook)) }
172
+ ) if to_subpath.exist?
173
+
174
+ to_subpath.parent.mkpath
175
+ FileUtils.cp_r from_subpath, to_subpath
176
+ end
177
+ else
178
+ to_path.parent.mkpath
179
+ FileUtils.cp_r from_path, to_path
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ def stage_install_paths(stage)
187
+ select_existing_paths = proc do |cookbook_path, paths|
188
+ paths.select {|from, _| cookbook_path.join(from).exist?}
189
+ end
190
+
191
+ common_paths = [['metadata.json', 'metadata.json']]
192
+
193
+ install_paths = Dir[vendor_path.join('*')]
194
+ .map(&Pathname.method(:new))
195
+ .map do |cookbook_path|
196
+ cookbook_name = File.basename cookbook_path
197
+ is_builder = (cookbook_name == self.name)
198
+ is_dimod = cookbook_name.start_with? 'dimod-'
199
+ dimod_enabled = is_dimod && enabled_modules.include?(cookbook_name)
200
+ paths = nil
201
+
202
+ if is_builder
203
+ common_dapp_paths = select_existing_paths.call(
204
+ cookbook_path,
205
+ [
206
+ *common_paths,
207
+ ["files/#{stage}/common", 'files/default'],
208
+ ["templates/#{stage}/common", 'templates/default'],
209
+ *enabled_recipes.flat_map do |recipe|
210
+ [["files/#{stage}/#{recipe}", 'files/default'],
211
+ ["templates/#{stage}/#{recipe}", 'templates/default']]
212
+ end
213
+ ]
214
+ )
215
+
216
+ recipe_paths = enabled_recipes
217
+ .map {|recipe| ["recipes/#{stage}/#{recipe}.rb", "recipes/#{recipe}.rb"]}
218
+ .select {|from, _| cookbook_path.join(from).exist?}
219
+
220
+ if recipe_paths.any?
221
+ paths = [*recipe_paths, *common_dapp_paths]
222
+ else
223
+ paths = [nil, *common_dapp_paths]
224
+ end
225
+ elsif is_dimod && dimod_enabled
226
+ common_dimod_paths = select_existing_paths.call(
227
+ cookbook_path,
228
+ [
229
+ *common_paths,
230
+ ["files/#{stage}", 'files/default'],
231
+ ['files/common', 'files/default'],
232
+ ["templates/#{stage}", 'templates/default'],
233
+ ['templates/common', 'templates/default'],
234
+ ["attributes/#{stage}.rb", "attributes/#{stage}.rb"],
235
+ ['attributes/common.rb', 'attributes/common.rb']
236
+ ]
237
+ )
238
+
239
+ recipe_path = "recipes/#{stage}.rb"
240
+ if cookbook_path.join(recipe_path).exist?
241
+ paths = [[recipe_path, recipe_path], *common_dimod_paths]
242
+ else
243
+ paths = [nil, *common_dimod_paths]
244
+ end
245
+ elsif !is_dimod
246
+ paths = [['.', '.']]
247
+ end
248
+
249
+ [cookbook_path, paths] if paths && paths.any?
250
+ end.compact
251
+ end
252
+
253
+ def _stage_cookbooks_path(stage)
254
+ builder.stage_build_path(stage).join('cookbooks')
255
+ end
256
+ end # Chef::Cookbook
257
+ end # Dapp::Builder
@@ -1,52 +1,54 @@
1
- module Dapp
2
- module Builder
3
- class Chef < Base
4
- # CookbookMetadata
5
- class CookbookMetadata
6
- # Parser
7
- class Parser
8
- def initialize(cookbook_metadata)
9
- @cookbook_metadata = cookbook_metadata
10
- parse
11
- end
12
-
13
- def name(name)
14
- @cookbook_metadata.name = name
15
- end
16
-
17
- def version(version)
18
- @cookbook_metadata.version = version
19
- end
20
-
21
- def depends(dependency, *_a, &_blk)
22
- @cookbook_metadata.depends << dependency.to_s
23
- end
24
-
25
- # rubocop:disable Style/MethodMissing
26
- def method_missing(*_a, &_blk)
27
- end
28
- # rubocop:enable Style/MethodMissing
29
-
30
- private
31
-
32
- def parse
33
- instance_eval(@cookbook_metadata.path.read, @cookbook_metadata.path.to_s)
34
- end
35
- end # Parser
36
-
37
- attr_reader :path
38
- attr_accessor :name
39
- attr_accessor :version
40
-
41
- def depends
42
- @depends ||= []
43
- end
44
-
45
- def initialize(path)
46
- @path = path
47
- @parser = Parser.new(self)
48
- end
49
- end # CookbookMetadata
50
- end # Chef
51
- end # Builder
52
- end # Dapp
1
+ module Dapp::Builder
2
+ class Chef::CookbookMetadata
3
+ class << self
4
+ def from_file(metadata_file_path)
5
+ metadata = self.new
6
+ FileParser.new(metadata_file_path, metadata)
7
+ metadata
8
+ end
9
+
10
+ def from_conf(conf)
11
+ # TODO
12
+ end
13
+ end # << self
14
+
15
+ class FileParser
16
+ def initialize(metadata_file_path, metadata)
17
+ @metadata_file_path = metadata_file_path
18
+ @metadata = metadata
19
+
20
+ parse
21
+ end
22
+
23
+ def name(name)
24
+ @metadata.name = name
25
+ end
26
+
27
+ def version(version)
28
+ @metadata.version = version
29
+ end
30
+
31
+ def depends(dependency, *_a, &_blk)
32
+ @metadata.depends << dependency.to_s
33
+ end
34
+
35
+ # rubocop:disable Style/MethodMissing
36
+ def method_missing(*_a, &_blk)
37
+ end
38
+ # rubocop:enable Style/MethodMissing
39
+
40
+ private
41
+
42
+ def parse
43
+ instance_eval(@metadata_file_path.read, @metadata_file_path.to_s)
44
+ end
45
+ end # FileParser
46
+
47
+ attr_accessor :name
48
+ attr_accessor :version
49
+
50
+ def depends
51
+ @depends ||= []
52
+ end
53
+ end # Chef::CookbookMetadata
54
+ end # Dapp::Builder