dapp 0.0.24 → 0.1.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 (78) hide show
  1. checksums.yaml +13 -5
  2. data/bin/dapp +17 -1
  3. data/config/en/common.yml +23 -0
  4. data/config/en/net_status.yml +24 -0
  5. data/lib/dapp.rb +68 -12
  6. data/lib/dapp/application.rb +57 -0
  7. data/lib/dapp/application/git_artifact.rb +26 -0
  8. data/lib/dapp/application/logging.rb +120 -0
  9. data/lib/dapp/application/path.rb +31 -0
  10. data/lib/dapp/application/tags.rb +65 -0
  11. data/lib/dapp/build/stage/app_install.rb +19 -0
  12. data/lib/dapp/build/stage/app_setup.rb +19 -0
  13. data/lib/dapp/build/stage/base.rb +106 -0
  14. data/lib/dapp/build/stage/from.rb +40 -0
  15. data/lib/dapp/build/stage/infra_install.rb +23 -0
  16. data/lib/dapp/build/stage/infra_setup.rb +19 -0
  17. data/lib/dapp/build/stage/source_1.rb +31 -0
  18. data/lib/dapp/build/stage/source_1_archive.rb +31 -0
  19. data/lib/dapp/build/stage/source_2.rb +20 -0
  20. data/lib/dapp/build/stage/source_3.rb +27 -0
  21. data/lib/dapp/build/stage/source_4.rb +31 -0
  22. data/lib/dapp/build/stage/source_5.rb +51 -0
  23. data/lib/dapp/build/stage/source_base.rb +109 -0
  24. data/lib/dapp/builder/base.rb +44 -0
  25. data/lib/dapp/builder/chef.rb +242 -0
  26. data/lib/dapp/builder/chef/berksfile.rb +54 -0
  27. data/lib/dapp/builder/shell.rb +16 -0
  28. data/lib/dapp/cli.rb +10 -44
  29. data/lib/dapp/cli/base.rb +55 -0
  30. data/lib/dapp/cli/build.rb +6 -140
  31. data/lib/dapp/cli/flush.rb +19 -0
  32. data/lib/dapp/cli/flush/build_cache.rb +26 -0
  33. data/lib/dapp/cli/flush/stage_cache.rb +23 -0
  34. data/lib/dapp/cli/list.rb +19 -0
  35. data/lib/dapp/cli/push.rb +59 -0
  36. data/lib/dapp/cli/smartpush.rb +19 -0
  37. data/lib/dapp/config/application.rb +98 -0
  38. data/lib/dapp/config/chef.rb +20 -0
  39. data/lib/dapp/config/docker.rb +39 -0
  40. data/lib/dapp/config/git_artifact.rb +78 -0
  41. data/lib/dapp/config/main.rb +23 -0
  42. data/lib/dapp/config/shell.rb +40 -0
  43. data/lib/dapp/controller.rb +103 -0
  44. data/lib/dapp/docker_image.rb +51 -0
  45. data/lib/dapp/error/application.rb +6 -0
  46. data/lib/dapp/error/base.rb +10 -0
  47. data/lib/dapp/error/build.rb +6 -0
  48. data/lib/dapp/error/config.rb +6 -0
  49. data/lib/dapp/error/controller.rb +6 -0
  50. data/lib/dapp/error/shellout.rb +6 -0
  51. data/lib/dapp/filelock.rb +1 -1
  52. data/lib/dapp/git_artifact.rb +43 -272
  53. data/lib/dapp/git_repo/base.rb +10 -12
  54. data/lib/dapp/git_repo/own.rb +7 -3
  55. data/lib/dapp/git_repo/remote.rb +14 -20
  56. data/lib/dapp/helper/cli.rb +66 -0
  57. data/lib/dapp/helper/i18n.rb +20 -0
  58. data/lib/dapp/helper/log.rb +72 -0
  59. data/lib/dapp/helper/paint.rb +27 -0
  60. data/lib/dapp/helper/sha256.rb +14 -0
  61. data/lib/dapp/helper/shellout.rb +41 -0
  62. data/lib/dapp/helper/streaming.rb +49 -0
  63. data/lib/dapp/helper/trivia.rb +27 -0
  64. data/lib/dapp/stage_image.rb +98 -0
  65. data/lib/dapp/version.rb +3 -1
  66. metadata +207 -51
  67. data/lib/dapp/atomizer.rb +0 -56
  68. data/lib/dapp/builder.rb +0 -230
  69. data/lib/dapp/builder/cascade_tagging.rb +0 -48
  70. data/lib/dapp/builder/centos7.rb +0 -47
  71. data/lib/dapp/builder/chefify.rb +0 -107
  72. data/lib/dapp/builder/ci_tagging.rb +0 -53
  73. data/lib/dapp/builder/git_tagging.rb +0 -21
  74. data/lib/dapp/builder/manual_tagging.rb +0 -22
  75. data/lib/dapp/builder/ubuntu1404.rb +0 -20
  76. data/lib/dapp/builder/ubuntu1604.rb +0 -20
  77. data/lib/dapp/docker.rb +0 -207
  78. data/lib/dapp/git_repo/chronicler.rb +0 -44
@@ -0,0 +1,44 @@
1
+ module Dapp
2
+ module Builder
3
+ # Base
4
+ class Base
5
+ attr_reader :application
6
+
7
+ def initialize(application)
8
+ @application = application
9
+ end
10
+
11
+ def infra_install(_image)
12
+ fail
13
+ end
14
+
15
+ def infra_install_checksum
16
+ fail
17
+ end
18
+
19
+ def infra_setup(_image)
20
+ fail
21
+ end
22
+
23
+ def infra_setup_checksum
24
+ fail
25
+ end
26
+
27
+ def app_install(_image)
28
+ fail
29
+ end
30
+
31
+ def app_install_checksum
32
+ fail
33
+ end
34
+
35
+ def app_setup(_image)
36
+ fail
37
+ end
38
+
39
+ def app_setup_checksum
40
+ fail
41
+ end
42
+ end # Base
43
+ end # Builder
44
+ end # Dapp
@@ -0,0 +1,242 @@
1
+ module Dapp
2
+ module Builder
3
+ # Chef
4
+ class Chef < Base
5
+ LOCAL_COOKBOOK_PATTERNS = %w(
6
+ recipes/**/*
7
+ files/**/*
8
+ templates/**/*
9
+ ).freeze
10
+
11
+ STAGE_LOCAL_COOKBOOK_PATTERNS = %w(
12
+ recipes/%{stage}.rb
13
+ recipes/*_%{stage}.rb
14
+ files/%{stage}/*
15
+ templates/%{stage}/*
16
+ ).freeze
17
+
18
+ DEFAULT_CHEFDK_IMAGE = 'dappdeps/chefdk:0.15.16-3'.freeze # TODO: config, DSL, DEFAULT_CHEFDK_IMAGE
19
+
20
+ [:infra_install, :infra_setup, :app_install, :app_setup].each do |stage|
21
+ define_method(:"#{stage}_checksum") { stage_cookbooks_checksum(stage) }
22
+
23
+ define_method(:"#{stage}") do |image|
24
+ install_stage_cookbooks(stage)
25
+ install_chef_solo_stage_config(stage)
26
+
27
+ unless stage_empty?(stage)
28
+ image.add_volumes_from(chefdk_container)
29
+ image.add_commands 'export PATH=/.dapp/deps/chefdk/bin:$PATH'
30
+
31
+ image.add_volume "#{stage_build_path(stage)}:#{container_stage_build_path(stage)}"
32
+ image.add_commands ['chef-solo',
33
+ "-c #{container_stage_config_path(stage)}",
34
+ "-o #{stage_cookbooks_runlist(stage).join(',')}"].join(' ')
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def project_name
42
+ application.config._root_app._name # FIXME: parse name from metadata.rb
43
+ end
44
+
45
+ def berksfile_path
46
+ application.home_path('Berksfile')
47
+ end
48
+
49
+ def berksfile
50
+ @berksfile ||= Berksfile.new(application.home_path, berksfile_path)
51
+ end
52
+
53
+ def berksfile_lock_checksum
54
+ path = application.home_path('Berksfile.lock')
55
+ application.hashsum path.read if path.exist?
56
+ end
57
+
58
+ # rubocop:disable Metrics/AbcSize
59
+ def stage_cookbooks_runlist(stage)
60
+ @stage_cookbooks_runlist ||= {}
61
+ @stage_cookbooks_runlist[stage] ||= [].tap do |res|
62
+ to_runlist_entrypoint = proc do |name, entrypoint|
63
+ entrypoint_file = stage_cookbooks_path(stage, name, 'recipes', "#{entrypoint}.rb")
64
+ next unless entrypoint_file.exist?
65
+ "#{name}::#{entrypoint}"
66
+ end
67
+
68
+ res.concat(application.config._chef._modules.map do |name|
69
+ to_runlist_entrypoint[name, stage]
70
+ end.compact)
71
+
72
+ res.concat(application.config._app_runlist.map(&:_name).map do |name|
73
+ subname_parts = name.split(project_name, 2)[1].split('-')
74
+ to_runlist_entrypoint[project_name, [*subname_parts, stage].join('_')]
75
+ end.compact)
76
+ end
77
+ end
78
+ # rubocop:enable Metrics/AbcSize
79
+
80
+ def local_cookbook_paths
81
+ @local_cookbook_paths ||= berksfile.local_cookbooks
82
+ .values
83
+ .map { |cookbook| cookbook[:path] }
84
+ .product(LOCAL_COOKBOOK_PATTERNS)
85
+ .map { |cb, dir| Dir[cb.join(dir)] }
86
+ .flatten
87
+ .map(&Pathname.method(:new))
88
+ end
89
+
90
+ def stage_cookbooks_vendored_paths(stage, with_files: false)
91
+ Dir[cookbooks_vendor_path('*')]
92
+ .map do|cookbook_path|
93
+ if ['mdapp-*', project_name].any? { |pattern| File.fnmatch(pattern, File.basename(cookbook_path)) }
94
+ STAGE_LOCAL_COOKBOOK_PATTERNS.map do |pattern|
95
+ Dir[File.join(cookbook_path, pattern % { stage: stage })]
96
+ end
97
+ elsif with_files
98
+ Dir[File.join(cookbook_path, '**/*')]
99
+ else
100
+ cookbook_path
101
+ end
102
+ end
103
+ .flatten
104
+ .map(&Pathname.method(:new))
105
+ end
106
+
107
+ def stage_cookbooks_checksum_path(stage)
108
+ application.build_cache_path("#{cookbooks_checksum}.#{stage}.checksum")
109
+ end
110
+
111
+ def stage_cookbooks_checksum(stage)
112
+ if stage_cookbooks_checksum_path(stage).exist?
113
+ stage_cookbooks_checksum_path(stage).read.strip
114
+ else
115
+ install_cookbooks
116
+
117
+ application.hashsum([_paths_checksum(stage_cookbooks_vendored_paths(stage, with_files: true)),
118
+ *application.config._chef._modules,
119
+ (stage == :infra_install) ? chefdk_image : nil].compact).tap do |checksum|
120
+ stage_cookbooks_checksum_path(stage).write "#{checksum}\n"
121
+ end
122
+ end
123
+ end
124
+
125
+ def cookbooks_checksum
126
+ @cookbooks_checksum ||= application.hashsum [
127
+ berksfile_lock_checksum,
128
+ _paths_checksum(local_cookbook_paths),
129
+ *application.config._chef._modules
130
+ ]
131
+ end
132
+
133
+ def chefdk_image
134
+ DEFAULT_CHEFDK_IMAGE # TODO: config, DSL, DEFAULT_CHEFDK_IMAGE
135
+ end
136
+
137
+ def chefdk_container_name # FIXME: hashsum(image) or dockersafe()
138
+ chefdk_image.tr('/', '_').tr(':', '_')
139
+ end
140
+
141
+ def chefdk_container
142
+ @chefdk_container ||= begin
143
+ if application.shellout("docker inspect #{chefdk_container_name}").exitstatus != 0
144
+ application.log_secondary_process(application.t(code: 'process.chefdk_loading'), short: true) do
145
+ application.shellout(
146
+ ['docker run',
147
+ '--restart=no',
148
+ "--name #{chefdk_container_name}",
149
+ "--volume /.dapp/deps/chefdk #{chefdk_image}",
150
+ '2>/dev/null'].join(' ')
151
+ )
152
+ end
153
+ end
154
+ chefdk_container_name
155
+ end
156
+ end
157
+
158
+ # rubocop:disable Metrics/MethodLength
159
+ def install_cookbooks
160
+ @install_cookbooks ||= begin
161
+ volumes_from = chefdk_container
162
+ application.log_secondary_process(application.t(code: 'process.berks_vendor')) do
163
+ application.shellout!(
164
+ ['docker run --rm',
165
+ "--volumes-from #{volumes_from}",
166
+ "--volume #{cookbooks_vendor_path.tap(&:mkpath)}:#{cookbooks_vendor_path}",
167
+ *berksfile.local_cookbooks
168
+ .values
169
+ .map { |cookbook| "--volume #{cookbook[:path]}:#{cookbook[:path]}" },
170
+ "--user #{Process.uid}:#{Process.gid}",
171
+ "--workdir #{berksfile_path.parent}",
172
+ '--env BERKSHELF_PATH=/tmp/berkshelf',
173
+ "ubuntu:14.04 /.dapp/deps/chefdk/bin/berks vendor #{cookbooks_vendor_path}"
174
+ ].join(' '),
175
+ log_verbose: application.log_verbose?
176
+ )
177
+
178
+ true
179
+ end
180
+ end
181
+ end
182
+ # rubocop:enable Metrics/MethodLength
183
+
184
+ def install_stage_cookbooks(stage)
185
+ stage_cookbooks_path(stage).mkpath
186
+ stage_cookbooks_vendored_paths(stage).each do |path|
187
+ new_path = stage_cookbooks_path(stage, path.relative_path_from(cookbooks_vendor_path))
188
+ new_path.parent.mkpath
189
+ FileUtils.cp_r path, new_path
190
+ end
191
+ end
192
+
193
+ def stage_empty?(stage)
194
+ stage_cookbooks_runlist(stage).empty?
195
+ end
196
+
197
+ def install_chef_solo_stage_config(stage)
198
+ stage_config_path(stage).write [
199
+ "file_cache_path \"/var/cache/dapp/chef\"\n",
200
+ "cookbook_path \"#{container_stage_cookbooks_path(stage)}\"\n"
201
+ ].join
202
+ end
203
+
204
+ def cookbooks_vendor_path(*path)
205
+ application.build_path('chef', 'vendored_cookbooks').join(*path)
206
+ end
207
+
208
+ def stage_build_path(stage, *path)
209
+ application.build_path(application.config._name, stage).join(*path)
210
+ end
211
+
212
+ def container_stage_build_path(_stage, *path)
213
+ path.compact.map(&:to_s).inject(Pathname.new('/chef_build'), &:+)
214
+ end
215
+
216
+ def stage_cookbooks_path(stage, *path)
217
+ stage_build_path(stage, 'cookbooks', *path)
218
+ end
219
+
220
+ def container_stage_cookbooks_path(stage, *path)
221
+ container_stage_build_path(stage, 'cookbooks', *path)
222
+ end
223
+
224
+ def stage_config_path(stage, *path)
225
+ stage_build_path(stage, 'config.rb', *path)
226
+ end
227
+
228
+ def container_stage_config_path(stage, *path)
229
+ container_stage_build_path(stage, 'config.rb', *path)
230
+ end
231
+
232
+ def _paths_checksum(paths)
233
+ application.hashsum [
234
+ *paths.map(&:to_s).sort,
235
+ *paths.reject(&:directory?)
236
+ .sort
237
+ .reduce(nil) { |a, e| application.hashsum [a, e.read].compact }
238
+ ]
239
+ end
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,54 @@
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, path: nil, **_kwargs)
14
+ @berksfile.add_local_cookbook_path(name, path) if path
15
+ end
16
+
17
+ def method_missing(*_a, &_blk)
18
+ end
19
+
20
+ private
21
+
22
+ def parse
23
+ instance_eval(@berksfile.path.read, @berksfile.path.to_s)
24
+ end
25
+ end # Parser
26
+
27
+ attr_reader :path
28
+ attr_reader :local_cookbooks
29
+
30
+ def initialize(home_path, path)
31
+ @home_path = home_path
32
+ @path = path
33
+ @local_cookbooks = {}
34
+ @parser = Parser.new(self)
35
+ end
36
+
37
+ def add_local_cookbook_path(name, path)
38
+ @local_cookbooks[name] = {
39
+ name: name,
40
+ path: @home_path.join(path)
41
+ }
42
+ end
43
+
44
+ def local_cookbook?(name)
45
+ local_cookbooks.key? name
46
+ end
47
+
48
+ def local_cookbook(name)
49
+ local_cookbooks[name]
50
+ end
51
+ end # Berksfile
52
+ end # Chef
53
+ end # Builder
54
+ end # Dapp
@@ -0,0 +1,16 @@
1
+ module Dapp
2
+ module Builder
3
+ # Shell
4
+ class Shell < Base
5
+ [:infra_install, :infra_setup, :app_install, :app_setup].each do |m|
6
+ define_method(:"#{m}_checksum") do
7
+ [application.config._shell.public_send("_#{m}"),
8
+ application.config._shell.public_send("_#{m}_cache_version")].flatten
9
+ end
10
+ define_method(:"#{m}") do |image|
11
+ image.add_commands(*application.config._shell.public_send("_#{m}"))
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/dapp/cli.rb CHANGED
@@ -3,18 +3,11 @@ require 'mixlib/cli'
3
3
  module Dapp
4
4
  # CLI
5
5
  class CLI
6
+ extend Helper::Cli
6
7
  include Mixlib::CLI
8
+ include Helper::Trivia
7
9
 
8
- class << self
9
- def parse_options(cli, argv)
10
- cli.parse_options(argv)
11
- rescue OptionParser::InvalidOption => e
12
- STDERR.puts "Error: #{e.message}"
13
- puts
14
- puts cli.opt_parser
15
- exit 1
16
- end
17
- end
10
+ SUBCOMMANDS = %w(build smartpush push list flush).freeze
18
11
 
19
12
  banner <<BANNER.freeze
20
13
  Usage: dapp [options] sub-command [sub-command options]
@@ -22,6 +15,10 @@ Usage: dapp [options] sub-command [sub-command options]
22
15
  Available subcommands: (for details, dapp SUB-COMMAND --help)
23
16
 
24
17
  dapp build [options] [PATTERN ...]
18
+ dapp push [options] [PATTERN] REPO
19
+ dapp smartpush [options] [PATTERN ...] REPOPREFIX
20
+ dapp list [options] [PATTERN ...]
21
+ dapp flush
25
22
 
26
23
  Options:
27
24
  BANNER
@@ -50,41 +47,10 @@ BANNER
50
47
  opt_parser.version = Dapp::VERSION
51
48
  end
52
49
 
53
- SUBCOMMANDS = %w(build).freeze
54
-
55
- def parse_subcommand(argv)
56
- if (index = argv.find_index { |v| SUBCOMMANDS.include? v })
57
- return [
58
- argv[0...index],
59
- argv[index],
60
- argv[index.next..-1]
61
- ]
62
- else
63
- return [
64
- argv,
65
- nil,
66
- []
67
- ]
68
- end
69
- end
70
-
71
50
  def run(argv = ARGV)
72
- argv, subcommand, subcommand_argv = parse_subcommand(argv)
73
-
74
- CLI.parse_options(self, argv)
75
-
76
- run_subcommand subcommand, subcommand_argv
77
- end
78
-
79
- def run_subcommand(subcommand, subcommand_argv)
80
- if subcommand
81
- self.class.const_get(subcommand.capitalize).new.run(subcommand_argv)
82
- else
83
- STDERR.puts 'Error: subcommand not passed'
84
- puts
85
- puts opt_parser
86
- exit 1
87
- end
51
+ argv, subcommand, subcommand_argv = self.class.parse_subcommand(self, argv)
52
+ self.class.parse_options(self, argv)
53
+ self.class.run_subcommand self, subcommand, subcommand_argv
88
54
  end
89
55
  end
90
56
  end
@@ -0,0 +1,55 @@
1
+ require 'mixlib/cli'
2
+
3
+ module Dapp
4
+ class CLI
5
+ # Base of CLI subcommands
6
+ class Base < CLI
7
+ option :dir,
8
+ long: '--dir PATH',
9
+ description: 'Change to directory',
10
+ on: :head
11
+
12
+ option :log_quiet,
13
+ short: '-q',
14
+ long: '--quiet',
15
+ description: 'Suppress logging',
16
+ on: :tail,
17
+ default: false,
18
+ boolean: true
19
+
20
+ option :log_verbose,
21
+ long: '--verbose',
22
+ description: 'Enable verbose output',
23
+ on: :tail,
24
+ default: false,
25
+ boolean: true
26
+
27
+ option :log_time,
28
+ long: '--log-time',
29
+ description: 'Enable output with time',
30
+ default: false,
31
+ boolean: true
32
+
33
+ option :log_color,
34
+ long: '--color MODE',
35
+ description: 'Display output in color on the terminal',
36
+ in: %w(auto on off),
37
+ default: 'auto'
38
+
39
+ option :dry_run,
40
+ long: '--dry-run',
41
+ default: false,
42
+ boolean: true
43
+
44
+ def initialize
45
+ self.class.options.merge!(Base.options)
46
+ super()
47
+ end
48
+
49
+ def run(argv = ARGV)
50
+ self.class.parse_options(self, argv)
51
+ Controller.new(cli_options: config, patterns: cli_arguments).public_send(class_to_lowercase)
52
+ end
53
+ end
54
+ end
55
+ end