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
data/lib/dapp/atomizer.rb DELETED
@@ -1,56 +0,0 @@
1
- module Dapp
2
- # "Transaction" journal with rollback (mainly to protect cache fill with unbuildable configuration)
3
- class Atomizer
4
- def initialize(builder, file_path, lock_timeout: 10)
5
- @builder = builder
6
- @file_path = file_path
7
- @lock_timeout = lock_timeout
8
- @file = open
9
-
10
- builder.register_atomizer self
11
- end
12
-
13
- def <<(path)
14
- file.puts path
15
- file.fsync
16
- end
17
-
18
- def commit!
19
- @file.truncate(0)
20
- @file.close
21
- @file = open
22
- end
23
-
24
- protected
25
-
26
- attr_reader :file_path
27
- attr_reader :builder
28
-
29
- attr_reader :lock_timeout
30
- attr_reader :file
31
-
32
- def open
33
- file = File.open(file_path, File::RDWR | File::CREAT, 0644)
34
-
35
- file.sync = true
36
-
37
- Timeout.timeout(lock_timeout) do
38
- file.flock(File::LOCK_EX)
39
- end
40
-
41
- if (not_commited_paths = file.read.lines.map(&:strip))
42
- FileUtils.rm_rf not_commited_paths
43
- end
44
-
45
- file.truncate(0)
46
- file.rewind
47
-
48
- file
49
- rescue Timeout::Error
50
- file.close
51
-
52
- STDERR.puts 'Atomizer already in use! Try again later.'
53
- exit 1
54
- end
55
- end
56
- end
data/lib/dapp/builder.rb DELETED
@@ -1,230 +0,0 @@
1
- module Dapp
2
- # Main class that does all stuff
3
- class Builder
4
- include Chefify
5
- include Centos7
6
- include Ubuntu1404
7
- include Ubuntu1604
8
- include CiTagging
9
- include ManualTagging
10
- include GitTagging
11
- include CascadeTagging
12
- include Filelock
13
-
14
- class << self
15
- def default_opts
16
- @default_opts ||= {}
17
- end
18
-
19
- def dappfiles_paths(path, pattern = '*')
20
- pattern.split('-').instance_eval { count.downto(1).map { |n| slice(0, n).join('-') } }
21
- .map { |p| Dir.glob(File.join([path, p, default_opts[:dappfile_name] || 'Dappfile'].compact)) }.find(&:any?) || []
22
- end
23
-
24
- def process_directory(path, pattern = '*')
25
- dappfiles_paths(path, pattern).map { |dappfile_path| process_file(dappfile_path, app_filter: pattern).builded_apps }.flatten
26
- end
27
-
28
- def process_file(dappfile_path, app_filter: '*')
29
- new(dappfile_path: dappfile_path, app_filter: app_filter) do |builder|
30
- builder.log "Processing application #{builder.name} (#{dappfile_path})"
31
-
32
- # indent all subsequent messages
33
- builder.indent_log
34
-
35
- # eval instructions from file
36
- builder.instance_eval File.read(dappfile_path), dappfile_path
37
-
38
- # commit atomizers
39
- builder.commit_atomizers!
40
- end
41
- end
42
- end
43
-
44
- def log(message)
45
- puts ' ' * opts[:log_indent] + ' * ' + message if opts[:log_verbose] || !opts[:log_quiet]
46
- end
47
-
48
- def shellout(*args, log_verbose: false, **kwargs)
49
- kwargs[:live_stream] = STDOUT if log_verbose && opts[:log_verbose]
50
- Mixlib::ShellOut.new(*args, :timeout => 3600, **kwargs).run_command.tap(&:error!)
51
- end
52
-
53
- def home_path(*path)
54
- path.compact.inject(Pathname.new(opts[:home_path]), &:+).expand_path.to_s
55
- end
56
-
57
- def build_path(*path)
58
- path.compact.inject(Pathname.new(opts[:build_path]), &:+).expand_path.tap do |p|
59
- FileUtils.mkdir_p p.parent
60
- end.to_s
61
- end
62
-
63
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
64
- def initialize(**options)
65
- opts.merge! self.class.default_opts
66
- opts.merge! options
67
-
68
- # default log indentation
69
- opts[:log_indent] = 0
70
-
71
- # basename
72
- if opts[:name]
73
- opts[:basename] = opts[:name]
74
- opts[:name] = nil
75
- elsif opts[:dappfile_path]
76
- opts[:basename] ||= Pathname.new(opts[:dappfile_path]).expand_path.parent.basename
77
- end
78
-
79
- # home path
80
- opts[:home_path] ||= Pathname.new(opts[:dappfile_path] || 'fakedir').parent.expand_path.to_s
81
-
82
- # build path
83
- opts[:build_path] = opts[:build_dir] ? opts[:build_dir] : home_path('build')
84
- opts[:build_path] = build_path opts[:basename] if opts[:shared_build_dir]
85
-
86
- # home branch
87
- @home_branch = shellout("git -C #{home_path} rev-parse --abbrev-ref HEAD").stdout.strip
88
-
89
- # atomizers
90
- @atomizers = []
91
-
92
- # account builded apps
93
- @builded_apps = []
94
-
95
- lock do
96
- yield self
97
- end
98
- end
99
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
100
-
101
- def indent_log
102
- opts[:log_indent] += 1
103
- end
104
-
105
- attr_reader :home_branch
106
-
107
- def builded_apps
108
- @builded_apps.dup
109
- end
110
-
111
- def docker
112
- docker_stack.last
113
- end
114
-
115
- def scope(&blk)
116
- stack_settings(&blk)
117
- end
118
-
119
- def app(name)
120
- log "Processing #{self.name}-#{name}"
121
-
122
- name = "#{opts[:name]}-#{name}" if opts[:name]
123
-
124
- stack_settings name: name, log_indent: opts[:log_indent] + 1 do
125
- docker.name name
126
-
127
- yield
128
- end
129
- end
130
-
131
- def name
132
- [opts[:basename], opts[:name]].compact.join '-'
133
- end
134
-
135
- def add_git_artifact(where_to_add, **kwargs)
136
- log "Adding artifact (to #{where_to_add})"
137
-
138
- # own repo
139
- repo = GitRepo::Own.new(self)
140
-
141
- # add artifact
142
- artifact = GitArtifact.new(self, repo, where_to_add, flush_cache: opts[:flush_cache], branch: home_branch, **kwargs)
143
- artifact.add_multilayer!
144
- end
145
-
146
- def add_remote_git_artifact(url, where_to_add, branch: opts[:git_artifact_branch] || home_branch, ssh_key_path: nil, **kwargs)
147
- log "Adding artifact from git (#{url} to #{where_to_add}, branch: #{branch})"
148
-
149
- # extract git repo name from url
150
- repo_name = url.gsub(%r{.*?([^\/ ]+)\.git}, '\\1')
151
-
152
- # clone or fetch
153
- repo = GitRepo::Remote.new(self, repo_name, url: url, ssh_key_path: ssh_key_path)
154
- repo.fetch!(branch)
155
-
156
- # add artifact
157
- artifact = GitArtifact.new(self, repo, where_to_add, flush_cache: opts[:flush_cache], branch: branch, **kwargs)
158
- artifact.add_multilayer!
159
- end
160
-
161
- # rubocop:disable Metrics/AbcSize
162
- def build(**_kwargs)
163
- # check app name
164
- unless !opts[:app_filter] || File.fnmatch("#{opts[:app_filter]}*", name)
165
- log "Skipped (does not match filter: #{opts[:app_filter]})!"
166
- return false
167
- end
168
-
169
- # build image
170
- log 'Building'
171
- image_id = docker.build
172
-
173
- # apply tagging
174
- %w(ci manual git cascade).each do |strategy|
175
- send "tag_#{strategy}", image_id
176
- end
177
-
178
- # push to repo
179
- if opts[:docker_repo]
180
- log 'Pushing to docker repo'
181
- docker.push name: name, repo: opts[:docker_repo]
182
- end
183
-
184
- # count it
185
- @builded_apps << name
186
-
187
- image_id
188
- end
189
- # rubocop:enable Metrics/AbcSize
190
-
191
- def register_atomizer(atomizer)
192
- atomizers << atomizer
193
- end
194
-
195
- def commit_atomizers!
196
- atomizers.each(&:commit!)
197
- end
198
-
199
- protected
200
-
201
- attr_reader :atomizers
202
-
203
- def opts
204
- opts_stack.last
205
- end
206
-
207
- def opts_stack
208
- @opts_stack ||= [{}]
209
- end
210
-
211
- def docker_stack
212
- @docker_stack ||= [Docker.new(self)]
213
- end
214
-
215
- def stack_settings(**options)
216
- opts_stack.push opts.merge(options).dup
217
- docker_stack.push docker.dup
218
-
219
- yield
220
- ensure
221
- docker_stack.pop
222
- opts_stack.pop
223
- end
224
-
225
- def lock(**kwargs, &block)
226
- filelock(build_path("#{home_branch}.lock"), error_message: "Application #{opts[:basename]} (#{home_branch}) in use! Try again later.", **kwargs,
227
- &block)
228
- end
229
- end
230
- end
@@ -1,48 +0,0 @@
1
- module Dapp
2
- class Builder
3
- # Cascade tagging strategy
4
- module CascadeTagging
5
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
6
- def tag_cascade(image_id)
7
- return unless opts[:tag_cascade]
8
-
9
- log 'Applying cascade tagging'
10
-
11
- opts[:build_history_length] ||= 10
12
-
13
- spec = {
14
- name: name,
15
- tag: home_branch,
16
- repo: opts[:docker_repo]
17
- }
18
-
19
- # return if nothing changed
20
- return if image_id == docker.image_id(spec)
21
-
22
- # remove excess tags
23
- tags_to_remove = docker.images(name: spec[:name], repo: spec[:repo])
24
- tags_to_remove.map! { |image| image[:tag] }
25
- tags_to_remove.select! { |tag| tag.start_with?("#{spec[:tag]}_") && tag.sub(/^#{spec[:tag]}_/, '').to_i >= opts[:build_history_length] }
26
- tags_to_remove.each do |tag_to_remove|
27
- docker.rmi spec.merge(tag: tag_to_remove)
28
- end
29
-
30
- # shift old images: 1 -> 2, 2 -> 3, ..., n -> n+1
31
- (opts[:build_history_length] - 1).downto(1).each do |n|
32
- origin = spec.merge(tag: "#{spec[:tag]}_#{n}")
33
-
34
- if docker.image_exist?(**origin)
35
- docker.tag origin, spec.merge(tag: "#{spec[:tag]}_#{n + 1}")
36
- end
37
- end
38
-
39
- # shift top -> 1
40
- docker.tag spec, spec.merge(tag: "#{spec[:tag]}_1") if docker.image_exist?(**spec)
41
-
42
- # tag top
43
- docker.tag image_id, spec
44
- end
45
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
46
- end
47
- end
48
- end
@@ -1,47 +0,0 @@
1
- module Dapp
2
- class Builder
3
- # Centos7 support
4
- module Centos7
5
- # rubocop:disable Metrics/MethodLength
6
- def from_centos7
7
- # use centos7
8
- docker.from 'centos:7'
9
-
10
- # add real systemd
11
- docker.env container: 'docker', step: :begining
12
- docker.run(
13
- 'yum -y update; yum clean all',
14
- '(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done)',
15
- 'rm -f /lib/systemd/system/multi-user.target.wants/*',
16
- 'rm -f /etc/systemd/system/*.wants/*',
17
- 'rm -f /lib/systemd/system/local-fs.target.wants/*',
18
- 'rm -f /lib/systemd/system/sockets.target.wants/*udev*',
19
- 'rm -f /lib/systemd/system/sockets.target.wants/*initctl*',
20
- 'rm -f /lib/systemd/system/basic.target.wants/*',
21
- 'rm -f /lib/systemd/system/anaconda.target.wants/*',
22
- 'rm -f /lib/systemd/system/systemd-remount-fs.service',
23
- 'rm -f /lib/systemd/system/sys-fs-fuse-connections.mount',
24
- step: :begining
25
- )
26
- docker.volume '/sys/fs/cgroup', step: :begining
27
- docker.cmd '/usr/sbin/init', step: :begining
28
-
29
- # cache yum fastestmirror
30
- docker.run 'yum makecache', step: :begining
31
-
32
- # TERM & utf8
33
- docker.run 'localedef -c -f UTF-8 -i en_US en_US.UTF-8', step: :begining
34
- docker.env TERM: 'xterm', LANG: 'en_US.UTF-8', LANGUAGE: 'en_US:en', LC_ALL: 'en_US.UTF-8', step: :begining
35
-
36
- # centos hacks
37
- docker.run(
38
- 'sed \'s/\(-\?session\s\+optional\s\+pam_systemd\.so.*\)/#\1/g\' -i /etc/pam.d/system-auth',
39
- 'yum install -y sudo git',
40
- 'echo \'Defaults:root !requiretty\' >> /etc/sudoers',
41
- step: :begining
42
- )
43
- end
44
- # rubocop:enable Metrics/MethodLength
45
- end
46
- end
47
- end
@@ -1,107 +0,0 @@
1
- module Dapp
2
- class Builder
3
- # Build using chef "dapp" cookbooks
4
- module Chefify
5
- def dappit(*extra_dapps, chef_version: '12.5.1', **_kwargs)
6
- log 'Adding dapp chef cookbook artifact and chef solo run'
7
-
8
- setup_dapp_chef chef_version
9
-
10
- # run chef solo
11
- [:prepare, :build, :setup].each do |step|
12
- # run chef-solo for extra dapps
13
- extra_dapps.each do |extra_dapp|
14
- if dapp_chef_cookbooks_artifact.exist_in_step? "cookbooks/mdapp-#{extra_dapp}/recipes/#{step}.rb", step
15
- docker.run "chef-solo -c /usr/share/dapp/chef_solo.rb -o mdapp-#{extra_dapp}::#{step},dapp-#{opts[:basename]}::void", step: step
16
- end
17
- end
18
-
19
- # run chef-solo for app
20
- recipe = [opts[:name], step].compact.join '-'
21
- if dapp_chef_cookbooks_artifact.exist_in_step? "cookbooks/dapp-#{opts[:basename]}/recipes/#{recipe}.rb", step
22
- docker.run "chef-solo -c /usr/share/dapp/chef_solo.rb -o dapp-#{opts[:basename]}::#{recipe}", step: step
23
- end
24
- end
25
- end
26
-
27
- def build_dapp(*args, extra_dapps: [], **kwargs, &blk)
28
- stack_settings do
29
- dappit(*extra_dapps, **kwargs)
30
-
31
- build(*args, **kwargs, &blk)
32
- end
33
- end
34
-
35
- protected
36
-
37
- def dapp_chef_cookbooks_artifact
38
- unless @dapp_chef_cookbooks_artifact
39
- # init cronicler
40
- repo = GitRepo::Chronicler.new(self, 'dapp_cookbooks', build_path: home_branch)
41
-
42
- # warmup berks cache
43
- Dir.mktmpdir('dapp_berks_warmup') do |tmpdir_path|
44
- FileUtils.cp home_path('Berksfile'), tmpdir_path
45
- FileUtils.cp home_path('metadata.rb'), tmpdir_path
46
- shellout 'berks install', cwd: tmpdir_path
47
- end
48
-
49
- # verify berks lock
50
- shellout "berks verify --berksfile=#{home_path 'Berksfile'}"
51
-
52
- # vendor cookbooks
53
- shellout "berks vendor --berksfile=#{home_path 'Berksfile'} #{repo.chronodir_path 'cookbooks'}", log_verbose: true
54
-
55
- # create void receipt
56
- FileUtils.touch repo.chronodir_path 'cookbooks', "dapp-#{opts[:basename]}", 'recipes', 'void.rb'
57
-
58
- # commit (if smth changed)
59
- repo.commit!
60
-
61
- # init artifact
62
- @dapp_chef_cookbooks_artifact = GitArtifact.new(self, repo, '/usr/share/dapp/chef_repo/cookbooks',
63
- cwd: 'cookbooks', build_path: home_branch, flush_cache: opts[:flush_cache])
64
- end
65
-
66
- @dapp_chef_cookbooks_artifact
67
- end
68
-
69
- def install_chef_and_setup_chef_solo(chef_version)
70
- docker.run(
71
- "curl -L https://www.opscode.com/chef/install.sh | bash -s -- -v #{chef_version}",
72
- 'mkdir -p /usr/share/dapp/chef_repo /var/cache/dapp/chef',
73
- 'echo file_cache_path \\"/var/cache/dapp/chef\\" > /usr/share/dapp/chef_solo.rb',
74
- 'echo cookbook_path \\"/usr/share/dapp/chef_repo/cookbooks\\" >> /usr/share/dapp/chef_solo.rb',
75
- step: :begining
76
- )
77
- end
78
-
79
- def run_chef_solo_for_mdapp_common
80
- [:prepare, :build, :setup].each do |step|
81
- if dapp_chef_cookbooks_artifact.exist_in_step? "cookbooks/mdapp-common/recipes/#{step}.rb", step
82
- docker.run "chef-solo -c /usr/share/dapp/chef_solo.rb -o mdapp-common::#{step},dapp-#{opts[:basename]}::void", step: step
83
- end
84
- end
85
- end
86
-
87
- def setup_dapp_chef(chef_version)
88
- if opts[:dapp_chef_version]
89
- raise "dapp chef version mismatch, version #{opts[:dapp_chef_version]} already installed" if opts[:dapp_chef_version] != chef_version
90
- return
91
- end
92
-
93
- # install chef, setup chef_solo
94
- install_chef_and_setup_chef_solo(chef_version)
95
-
96
- # add cookbooks
97
- dapp_chef_cookbooks_artifact.add_multilayer!
98
-
99
- # mark chef as installed
100
- opts[:dapp_chef_version] = chef_version
101
-
102
- # run chef solo for mdapp-common
103
- run_chef_solo_for_mdapp_common
104
- end
105
- end
106
- end
107
- end