dapp 0.0.24 → 0.1.0

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