dapp 0.3.0 → 0.3.1

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTM1NTkwNWNjMzM0YTkzYTdlOGMzODY4MzE4ZGQ5YWZmNjI0YmU5Zg==
4
+ YzZiYzcxYjE1NWZlOGFhNTkzNzYzYTU5OTBhYmFmMTcxNjJkOGE5YQ==
5
5
  data.tar.gz: !binary |-
6
- YjM5ODYyYzIzNDA3YjkyODFkYThjYjE2NTFhNDA4MGQxM2IyZGE2Mg==
6
+ NWM2YTA4OTY5MTRhZmU2YzUxMDhmNWQwMmRmNmIzY2JjOWE0MTI0Ng==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OThjNmU0YmUyODZlODdkNzI2YjdiM2MyZDA4YmZkOWY2NTdmM2Y4MGJkYWM1
10
- MTliMzkyMjcwMThiMGMzNTE2MGQyMGI0NGMyMTNlMDdkM2M5NDMzYjcxZTc0
11
- YzM3YmMzZTkyNGYwZTM4YmJjMjY5YmFkN2U3YmVmMTgwODA5ZWY=
9
+ MDljYWUxMTk5MDM2ZGE3YmQ4MWUzMGRlNTU4ZTMwYmQ1OGRkOTQzMDBkMDU2
10
+ YTkzNTgzNmFmMGY3YjcxMjA5MDg4Y2I0OGE1MmZhMDIwOWRkM2FhMWM4Mzhm
11
+ Nzc1ZTFmNzIxNWM1NWY5MWNhNTQzZjQzZmU5NDg4YTYyNWZkY2I=
12
12
  data.tar.gz: !binary |-
13
- OWRiZGIzNzY0MTQzYzk3OTJlMDYxNDA4ZjI2OWEwZGQzNDQ2NTQ3NjQ4MGUx
14
- N2Y4NTVmY2UyNTNhMGUzNmUwMTI1Zjg3ODJjZDhlYmIwZDIyZDgxZTFiZmRm
15
- YWUwNGU0ZmY1MzJlNmU2ZDNhYmRmYTg1ZWFmODU1ZTYxMWFjZDQ=
13
+ ZGIzNTcyYjRhMjM4MTIxYjJiYWU4ODU5NDYzYjQxZjhlZjA3MGI4OGNlMzVj
14
+ Y2U0NTdhOThiMGJmMTVmODYyYTUzMWQ4NDkzNzZhYzgwYTBlMTc3MWU0NGU5
15
+ MDg5ZDQxYjg0Y2YxZWIxZDM0MTNkMWE0MDY4ZjAyYTE5MGM5NTg=
data/bin/dapp CHANGED
@@ -10,7 +10,7 @@ begin
10
10
  rescue Dapp::Error::Shellout => e
11
11
  $stderr.puts(Dapp::Helper::NetStatus.message(e))
12
12
  exit 1
13
- rescue Dapp::Error::Base => e
13
+ rescue Dapp::Error::Base, NetStatus::Exception => e
14
14
  $stderr.puts(Dapp::Helper::Paint.paint_string(Dapp::Helper::NetStatus.message(e), :warning))
15
15
  exit 1
16
16
  rescue Interrupt => _e
@@ -2,10 +2,14 @@ en:
2
2
  common:
3
3
  image:
4
4
  signature: "signature: %{signature}"
5
- info: "date: %{date}\nsize: %{size} MB"
5
+ info:
6
+ date: "date: %{value}"
7
+ size: "size: %{value} MB"
8
+ difference: "difference: %{value} MB"
6
9
  commands: "commands:"
7
10
  process:
8
11
  artifact_copy: "copying artifact '%{name}'"
12
+ artifact_building: "building artifact '%{name}'"
9
13
  git_artifact_loading: 'loading git_artifact'
10
14
  git_artifact_clone: "cloning remote git_artifact '%{name}'"
11
15
  git_artifact_fetch: "fetching remote git_artifact '%{name}'"
@@ -22,6 +26,7 @@ en:
22
26
  default: '[FAILED]'
23
27
  state:
24
28
  using_cache: '[USING CACHE]'
29
+ not_present: '[NOT PRESENT]'
25
30
  build: '[BUILD]'
26
31
  push: '[PUSH]'
27
32
  introspect:
@@ -1,6 +1,6 @@
1
1
  en:
2
2
  net_status:
3
- missing_translation: "Missing translation for code: '%{code}'."
3
+ missing_translation: "Missing translation for code: '%{code}'!"
4
4
  shellout:
5
5
  shell_command_failed: ">>> START STREAM\n%{stream}\n>>> END STREAM"
6
6
  application:
@@ -23,5 +23,7 @@ en:
23
23
  builder_type_conflict: 'Conflict between builder types!'
24
24
  builder_type_unsupported: "Defined unsupported builder type `%{type}`!"
25
25
  docker_from_not_defined: "Docker `from` not defined!"
26
- artifact_unexpected_attribute: "Artifact doesn't have attribute '%{attr}'!"
27
- git_artifact_unexpected_attribute: "'%{type}' git artifact doesn't have attribute '%{attr}'!"
26
+ artifact_unexpected_attribute: "Artifact doesn't has attribute '%{attr}'!"
27
+ stage_artifact_not_associated: "Artifact not associated with any stage!"
28
+ stage_artifact_incorrect_associated_value: "Artifact option '%{option}' has incorrect value '%{value}'!"
29
+ git_artifact_unexpected_attribute: "'%{type}' git artifact doesn't has attribute '%{attr}'!"
@@ -31,9 +31,9 @@ require 'dapp/cli/build'
31
31
  require 'dapp/cli/push'
32
32
  require 'dapp/cli/smartpush'
33
33
  require 'dapp/cli/list'
34
- require 'dapp/cli/flush'
35
- require 'dapp/cli/flush/stages'
36
- require 'dapp/cli/flush/metadata'
34
+ require 'dapp/cli/stages'
35
+ require 'dapp/cli/stages/flush'
36
+ require 'dapp/cli/stages/cleanup'
37
37
  require 'dapp/cli/run'
38
38
  require 'dapp/filelock'
39
39
  require 'dapp/config/application'
@@ -48,6 +48,8 @@ require 'dapp/builder/chef'
48
48
  require 'dapp/builder/chef/cookbook_metadata'
49
49
  require 'dapp/builder/chef/berksfile'
50
50
  require 'dapp/builder/shell'
51
+ require 'dapp/build/stage/mod/artifact'
52
+ require 'dapp/build/stage/mod/logging'
51
53
  require 'dapp/build/stage/base'
52
54
  require 'dapp/build/stage/source_base'
53
55
  require 'dapp/build/stage/from'
@@ -29,11 +29,8 @@ module Dapp
29
29
  end
30
30
 
31
31
  def build!
32
- log_step(config._name)
33
- with_log_indent do
34
- last_stage.build!
35
- last_stage.save_in_cache!
36
- end
32
+ last_stage.build!
33
+ last_stage.save_in_cache!
37
34
  ensure
38
35
  FileUtils.rm_rf(tmp_path)
39
36
  end
@@ -71,10 +68,6 @@ module Dapp
71
68
  @builder ||= Builder.const_get(config._builder.capitalize).new(self)
72
69
  end
73
70
 
74
- def meta_options
75
- { cli_options: cli_options, ignore_git_fetch: ignore_git_fetch }
76
- end
77
-
78
71
  protected
79
72
 
80
73
  attr_reader :last_stage
@@ -5,6 +5,8 @@ module Dapp
5
5
  class Base
6
6
  include Helper::Sha256
7
7
  include Helper::Trivia
8
+ include Mod::Artifact
9
+ include Mod::Logging
8
10
 
9
11
  attr_accessor :prev_stage, :next_stage
10
12
  attr_reader :application
@@ -16,28 +18,14 @@ module Dapp
16
18
  @next_stage.prev_stage = self
17
19
  end
18
20
 
19
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
20
21
  def build!
21
22
  return if should_be_skipped?
22
23
  prev_stage.build! if prev_stage
23
- begin
24
- if image.tagged?
25
- application.log_state(name, state: application.t(code: 'state.using_cache'))
26
- elsif application.dry_run?
27
- application.log_state(name, state: application.t(code: 'state.build'), styles: { status: :success })
28
- else
29
- application.log_process(name, process: application.t(code: 'status.process.building'), short: should_be_not_detailed?) do
30
- image_build!
31
- end
32
- end
33
- ensure
34
- log_build
35
- end
24
+ image_build
36
25
  raise Exception::IntrospectImage,
37
26
  message: application.t(code: 'introspect.stage', data: { name: name }),
38
27
  data: { built_id: image.built_id, options: image.send(:prepared_options) } if should_be_introspected?
39
28
  end
40
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
41
29
 
42
30
  def save_in_cache!
43
31
  return if image.tagged?
@@ -53,6 +41,7 @@ module Dapp
53
41
  @image ||= begin
54
42
  Image::Stage.new(name: image_name, from: from_image).tap do |image|
55
43
  image.add_volume "#{application.tmp_path}:#{application.container_tmp_path}"
44
+ image.add_change_label dapp: application.config._basename
56
45
  before_artifacts.each { |artifact| apply_artifact(artifact, image) }
57
46
  yield image if block_given?
58
47
  after_artifacts.each { |artifact| apply_artifact(artifact, image) }
@@ -66,19 +55,25 @@ module Dapp
66
55
  class_to_lowercase.to_sym
67
56
  end
68
57
 
69
- def should_be_not_detailed?
70
- image.send(:bash_commands).empty?
71
- end
72
-
73
- def should_be_skipped?
74
- image.tagged? && !application.log_verbose? && application.cli_options[:introspect_stage].nil?
75
- end
76
-
77
- def should_be_introspected?
78
- application.cli_options[:introspect_stage] == name && !application.dry_run? && !application.is_artifact
58
+ # rubocop:disable Metrics/AbcSize
59
+ def image_build
60
+ if image.tagged?
61
+ application.log_state(name, state: application.t(code: 'state.using_cache'))
62
+ elsif should_be_not_present?
63
+ application.log_state(name, state: application.t(code: 'state.not_present'))
64
+ elsif application.dry_run?
65
+ application.log_state(name, state: application.t(code: 'state.build'), styles: { status: :success })
66
+ else
67
+ application.log_process(name, process: application.t(code: 'status.process.building'), short: should_be_not_detailed?) do
68
+ image_do_build
69
+ end
70
+ end
71
+ ensure
72
+ log_build
79
73
  end
74
+ # rubocop:enable Metrics/AbcSize
80
75
 
81
- def image_build!
76
+ def image_do_build
82
77
  image.build!(log_verbose: application.log_verbose?,
83
78
  log_time: application.log_time?,
84
79
  introspect_error: application.cli_options[:introspect_error],
@@ -92,97 +87,8 @@ module Dapp
92
87
  end
93
88
 
94
89
  def image_name
95
- "dapp:#{signature}"
96
- end
97
-
98
- def image_info
99
- date, size = image.info
100
- _date, from_size = from_image.info
101
- [date, (from_size.to_f - size.to_f).abs]
102
- end
103
-
104
- def format_image_info
105
- date, size = image_info
106
- application.t(code: 'image.info', data: { date: Time.parse(date).localtime, size: size.to_f.round(2) })
107
- end
108
-
109
- # rubocop:disable Metrics/AbcSize
110
- def log_build
111
- application.with_log_indent do
112
- application.log_info application.t(code: 'image.signature', data: { signature: image_name })
113
- application.log_info format_image_info if image.tagged?
114
- unless (bash_commands = image.send(:bash_commands)).empty?
115
- application.log_info application.t(code: 'image.commands')
116
- application.with_log_indent { application.log_info bash_commands.join("\n") }
117
- end
118
- end if application.log? && application.log_verbose?
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(' && ')
90
+ "#{application.config._basename}-dappstage:#{signature}"
184
91
  end
185
- # rubocop:enable Metrics/ParameterLists
186
92
  end # Base
187
93
  end # Stage
188
94
  end # Build
@@ -17,7 +17,7 @@ module Dapp
17
17
 
18
18
  protected
19
19
 
20
- def image_build!
20
+ def image_do_build
21
21
  from_image.pull!(log_time: application.log_time?)
22
22
  super
23
23
  end
@@ -31,10 +31,6 @@ module Dapp
31
31
  def from_image
32
32
  @from_image ||= Image::Stage.new(name: from_image_name)
33
33
  end
34
-
35
- def image_info
36
- image.info
37
- end
38
34
  end # Prepare
39
35
  end # Stage
40
36
  end # Build
@@ -0,0 +1,92 @@
1
+ module Dapp
2
+ module Build
3
+ module Stage
4
+ # Mod
5
+ module Mod
6
+ # Artifact
7
+ module Artifact
8
+ def before_artifacts
9
+ @before_artifacts ||= do_artifacts(application.config._artifact.select { |artifact| artifact._before == name })
10
+ end
11
+
12
+ def after_artifacts
13
+ @after_artifacts ||= do_artifacts(application.config._artifact.select { |artifact| artifact._after == name })
14
+ end
15
+
16
+ def do_artifacts(artifacts)
17
+ verbose = application.log_verbose?
18
+ artifacts.map do |artifact|
19
+ process = application.t(code: 'process.artifact_building', data: { name: artifact._config._name })
20
+ application.log_secondary_process(process, short: !verbose) do
21
+ application.with_log_indent do
22
+ {
23
+ name: artifact._config._name,
24
+ options: artifact._artifact_options,
25
+ app: Application.new(artifact_app_options(artifact, verbose)).tap(&:build!)
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def artifact_app_options(artifact, verbose)
33
+ {
34
+ config: artifact._config,
35
+ cli_options: application.cli_options.merge(log_quiet: !verbose),
36
+ ignore_git_fetch: application.ignore_git_fetch,
37
+ is_artifact: true
38
+ }
39
+ end
40
+
41
+ def artifacts_signatures
42
+ (before_artifacts + after_artifacts).map { |artifact| hashsum [artifact[:app].signature, artifact[:options]] }
43
+ end
44
+
45
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
46
+ def apply_artifact(artifact, image)
47
+ return if application.dry_run?
48
+
49
+ artifact_name = artifact[:name]
50
+ app = artifact[:app]
51
+ cwd = artifact[:options][:cwd]
52
+ paths = artifact[:options][:paths]
53
+ owner = artifact[:options][:owner]
54
+ group = artifact[:options][:group]
55
+ where_to_add = artifact[:options][:where_to_add]
56
+
57
+ docker_options = ['--rm',
58
+ "--volume #{application.tmp_path('artifact', artifact_name)}:#{app.container_tmp_path(artifact_name)}",
59
+ '--entrypoint /bin/sh']
60
+ commands = safe_cp(where_to_add, app.container_tmp_path(artifact_name), Process.uid, Process.gid)
61
+ application.log_secondary_process(application.t(code: 'process.artifact_copy', data: { name: artifact_name }), short: true) do
62
+ app.run(docker_options, Array(application.shellout_pack(commands)))
63
+ end
64
+
65
+ commands = safe_cp(application.container_tmp_path('artifact', artifact_name), where_to_add, owner, group, cwd, paths)
66
+ image.add_commands commands
67
+ end
68
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
69
+
70
+ # rubocop:disable Metrics/ParameterLists
71
+ def safe_cp(from, to, owner, group, cwd = '', paths = [])
72
+ credentials = ''
73
+ credentials += "-o #{owner} " if owner
74
+ credentials += "-g #{group} " if group
75
+
76
+ copy_files = lambda do |from_, cwd_, path_ = ''|
77
+ "find #{File.join(from_, cwd_, path_)} -type f -exec bash -ec 'install -D #{credentials} {} " \
78
+ "#{File.join(to, "$(echo {} | sed -e \"s/#{File.join(from_, cwd_).gsub('/', '\\/')}//g\")")}' \\;"
79
+ end
80
+
81
+ commands = []
82
+ commands << ['install', credentials, '-d', to].join(' ')
83
+ commands.concat(paths.empty? ? Array(copy_files.call(from, cwd)) : paths.map { |path| copy_files.call(from, cwd, path) })
84
+ commands << "find #{to} -type d -exec bash -ec 'install -d #{credentials} {}' \\;"
85
+ commands.join(' && ')
86
+ end
87
+ # rubocop:enable Metrics/ParameterLists
88
+ end
89
+ end # Mod
90
+ end # Stage
91
+ end # Build
92
+ end # Dapp
@@ -0,0 +1,64 @@
1
+ module Dapp
2
+ module Build
3
+ module Stage
4
+ # Mod
5
+ module Mod
6
+ # Logging
7
+ module Logging
8
+ def log_build
9
+ application.with_log_indent do
10
+ application.log_info application.t(code: 'image.signature', data: { signature: image_name })
11
+ log_image_info
12
+ log_image_commands
13
+ end if application.log? && application.log_verbose?
14
+ end
15
+
16
+ def log_image_commands
17
+ return if (bash_commands = image.send(:bash_commands)).empty?
18
+ application.log_info application.t(code: 'image.commands')
19
+ application.with_log_indent { application.log_info bash_commands.join("\n") }
20
+ end
21
+
22
+ def log_image_info
23
+ return unless image.tagged?
24
+ date, size = image_info
25
+ application.log_info application.t(code: 'image.info.date', data: { value: date })
26
+ size_code = size_difference? ? 'image.info.difference' : 'image.info.size'
27
+ application.log_info application.t(code: size_code, data: { value: size })
28
+ end
29
+
30
+ def image_info
31
+ date, size = image.info
32
+ if size_difference?
33
+ _date, from_size = from_image.info
34
+ size = size.to_f - from_size.to_f
35
+ end
36
+
37
+ [Time.parse(date).localtime, size.to_f.round(2)]
38
+ end
39
+
40
+ def size_difference?
41
+ from_image.tagged? && !prev_stage.nil?
42
+ end
43
+
44
+ def should_be_skipped?
45
+ image.tagged? && !application.log_verbose? && application.cli_options[:introspect_stage].nil?
46
+ end
47
+
48
+ def should_be_not_present?
49
+ return false if next_stage.nil?
50
+ next_stage.image.tagged? || next_stage.should_be_not_present?
51
+ end
52
+
53
+ def should_be_not_detailed?
54
+ image.send(:bash_commands).empty?
55
+ end
56
+
57
+ def should_be_introspected?
58
+ application.cli_options[:introspect_stage] == name && !application.dry_run? && !application.is_artifact
59
+ end
60
+ end
61
+ end # Mod
62
+ end # Stage
63
+ end # Build
64
+ end # Dapp
@@ -65,20 +65,19 @@ module Dapp
65
65
  @cookbook_metadata ||= CookbookMetadata.new(cookbook_metadata_path)
66
66
  end
67
67
 
68
-
69
68
  def berksfile_lock_checksum
70
69
  application.hashsum berksfile_lock_path.read if berksfile_lock_path.exist?
71
70
  end
72
71
 
73
72
  def local_cookbook_paths_for_checksum
74
73
  @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)] }
80
- .flatten
81
- .map(&Pathname.method(:new))
74
+ .local_cookbooks
75
+ .values
76
+ .map { |cookbook| cookbook[:path] }
77
+ .product(LOCAL_COOKBOOK_CHECKSUM_PATTERNS)
78
+ .map { |cb, dir| Dir[cb.join(dir)] }
79
+ .flatten
80
+ .map(&Pathname.method(:new))
82
81
  end
83
82
 
84
83
  def stage_cookbooks_paths_for_checksum(stage)
@@ -95,14 +94,14 @@ module Dapp
95
94
  stage_cookbooks_checksum_path(stage).read.strip
96
95
  else
97
96
  checksum = if stage == :chef_cookbooks
98
- cookbooks_checksum
99
- else
100
- application.hashsum [
101
- _paths_checksum(stage_cookbooks_paths_for_checksum(stage)),
102
- *application.config._chef._modules,
103
- stage == :infra_install ? chefdk_image : nil
104
- ].compact
105
- end
97
+ cookbooks_checksum
98
+ else
99
+ application.hashsum [
100
+ _paths_checksum(stage_cookbooks_paths_for_checksum(stage)),
101
+ *application.config._chef._modules,
102
+ stage == :infra_install ? chefdk_image : nil
103
+ ].compact
104
+ end
106
105
 
107
106
  stage_cookbooks_checksum_path(stage).write "#{checksum}\n"
108
107
  checksum
@@ -117,7 +116,6 @@ module Dapp
117
116
  ]
118
117
  end
119
118
 
120
-
121
119
  def chefdk_image
122
120
  DEFAULT_CHEFDK_IMAGE # TODO: config, DSL, DEFAULT_CHEFDK_IMAGE
123
121
  end
@@ -143,7 +141,6 @@ module Dapp
143
141
  end
144
142
  end
145
143
 
146
-
147
144
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
148
145
  def install_cookbooks
149
146
  volumes_from = chefdk_container
@@ -187,7 +184,7 @@ module Dapp
187
184
  # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
188
185
 
189
186
  def _cookbooks_vendor_path
190
- application.metadata_path("cookbooks.#{cookbooks_checksum}")
187
+ application.tmp_path(application.config._name, "cookbooks.#{cookbooks_checksum}")
191
188
  end
192
189
 
193
190
  def cookbooks_vendor_path(*path)
@@ -196,7 +193,6 @@ module Dapp
196
193
  end.join(*path)
197
194
  end
198
195
 
199
-
200
196
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
201
197
  def install_stage_cookbooks(stage)
202
198
  @install_stage_cookbooks ||= {}
@@ -204,36 +200,35 @@ module Dapp
204
200
  common_paths = proc do |cookbook_path|
205
201
  [['metadata.json', 'metadata.json'],
206
202
  ["files/#{stage}", 'files/default'],
207
- ["templates/#{stage}", 'templates/default']
208
- ].select { |from, _| cookbook_path.join(from).exist? }
203
+ ["templates/#{stage}", 'templates/default']].select { |from, _| cookbook_path.join(from).exist? }
209
204
  end
210
205
 
211
206
  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
207
+ .map(&Pathname.method(:new))
208
+ .map do |cookbook_path|
209
+ cookbook_name = File.basename cookbook_path
210
+ is_project = (cookbook_name == project_name)
211
+ is_mdapp = cookbook_name.start_with? 'mdapp-'
212
+ mdapp_enabled = is_mdapp && application.config._chef._modules.include?(cookbook_name)
213
+
214
+ paths = if is_project
215
+ recipe_paths = application.config._chef._recipes
216
+ .map { |recipe| ["recipes/#{stage}/#{recipe}.rb", "recipes/#{recipe}.rb"] }
217
+ .select { |from, _| cookbook_path.join(from).exist? }
218
+
219
+ (recipe_paths + common_paths[cookbook_path]) if recipe_paths.any?
220
+ elsif is_mdapp && mdapp_enabled
221
+ recipe_path = "recipes/#{stage}.rb"
222
+ if cookbook_path.join(recipe_path).exist?
223
+ [[recipe_path, recipe_path]] + common_paths[cookbook_path]
224
+ end
225
+ else
226
+ [['.', '.']]
227
+ end
228
+
229
+ [cookbook_path, paths] if paths && paths.any?
230
+ end
231
+ .compact
237
232
 
238
233
  stage_cookbooks_path(stage).mkpath
239
234
  install_paths.each do |cookbook_path, paths|
@@ -279,7 +274,6 @@ module Dapp
279
274
  stage_tmp_path(stage, 'cookbooks', *path)
280
275
  end
281
276
 
282
-
283
277
  def install_chef_solo_stage_config(stage)
284
278
  @install_chef_solo_stage_config ||= {}
285
279
  @install_chef_solo_stage_config[stage] ||= true.tap do
@@ -295,7 +289,6 @@ module Dapp
295
289
  container_stage_tmp_path(stage, 'config.rb', *path)
296
290
  end
297
291
 
298
-
299
292
  def stage_tmp_path(stage, *path)
300
293
  application.tmp_path(application.config._name, stage).join(*path)
301
294
  end
@@ -7,7 +7,7 @@ module Dapp
7
7
  include Mixlib::CLI
8
8
  include Helper::Trivia
9
9
 
10
- SUBCOMMANDS = %w(build smartpush push list run flush).freeze
10
+ SUBCOMMANDS = %w(build smartpush push list run stages).freeze
11
11
 
12
12
  banner <<BANNER.freeze
13
13
  Usage: dapp [options] sub-command [sub-command options]
@@ -19,7 +19,7 @@ dapp push [options] [PATTERN] REPO
19
19
  dapp smartpush [options] [PATTERN ...] REPOPREFIX
20
20
  dapp list [options] [PATTERN ...]
21
21
  dapp run [options] [PATTERN] [DOCKER ARGS]
22
- dapp flush
22
+ dapp stages
23
23
 
24
24
  Options:
25
25
  BANNER
@@ -3,16 +3,16 @@ require 'mixlib/cli'
3
3
  module Dapp
4
4
  class CLI
5
5
  # CLI flush subcommand
6
- class Flush < CLI
7
- SUBCOMMANDS = %w(metadata stages).freeze
6
+ class Stages < CLI
7
+ SUBCOMMANDS = %w(flush cleanup).freeze
8
8
 
9
9
  banner <<BANNER.freeze
10
10
  Version: #{Dapp::VERSION}
11
11
 
12
12
  Available subcommands: (for details, dapp SUB-COMMAND --help)
13
13
 
14
- dapp flush metadata
15
- dapp flush stages
14
+ dapp stages flush
15
+ dapp stages cleanup
16
16
  BANNER
17
17
  end
18
18
  end
@@ -2,23 +2,19 @@ require 'mixlib/cli'
2
2
 
3
3
  module Dapp
4
4
  class CLI
5
- class Flush
6
- # Flush metadata subcommand
7
- class Metadata < Base
5
+ class Stages
6
+ # Flush stages subcommand
7
+ class Cleanup < Base
8
8
  banner <<BANNER.freeze
9
9
  Version: #{Dapp::VERSION}
10
10
 
11
11
  Usage:
12
- dapp flush metadata
12
+ dapp stages cleanup
13
13
  Options:
14
14
  BANNER
15
- option :metadata_dir,
16
- long: '--metadata-dir PATH',
17
- description: 'Metadata directory'
18
-
19
15
  def run(argv = ARGV)
20
16
  self.class.parse_options(self, argv)
21
- Controller.new(cli_options: config, patterns: cli_arguments).flush_metadata
17
+ Controller.new(cli_options: config, patterns: cli_arguments).stages_cleanup
22
18
  end
23
19
  end
24
20
  end
@@ -2,20 +2,19 @@ require 'mixlib/cli'
2
2
 
3
3
  module Dapp
4
4
  class CLI
5
- class Flush
5
+ class Stages
6
6
  # Flush stages subcommand
7
- class Stages < Flush
7
+ class Flush < Base
8
8
  banner <<BANNER.freeze
9
9
  Version: #{Dapp::VERSION}
10
10
 
11
11
  Usage:
12
- dapp flush stages
12
+ dapp stages flush
13
13
  Options:
14
14
  BANNER
15
-
16
15
  def run(argv = ARGV)
17
16
  self.class.parse_options(self, argv)
18
- Controller.flush_stages
17
+ Controller.new(cli_options: config, patterns: cli_arguments).stages_flush
19
18
  end
20
19
  end
21
20
  end
@@ -2,9 +2,9 @@ module Dapp
2
2
  module Config
3
3
  # Application
4
4
  class Application
5
- attr_reader :_name
6
5
  attr_reader :_builder
7
6
  attr_reader :_home_path
7
+ attr_reader :_basename
8
8
  attr_reader :_docker
9
9
  attr_reader :_git_artifact
10
10
  attr_reader :_artifact
@@ -70,6 +70,10 @@ module Dapp
70
70
  @_builder = type
71
71
  end
72
72
 
73
+ def _name
74
+ @_name || @_basename
75
+ end
76
+
73
77
  def _apps
74
78
  @_apps.empty? ? [self] : @_apps.flatten
75
79
  end
@@ -98,6 +102,7 @@ module Dapp
98
102
  Application.new(self).tap do |app|
99
103
  app.instance_variable_set(:'@_builder', _builder)
100
104
  app.instance_variable_set(:'@_home_path', _home_path)
105
+ app.instance_variable_set(:'@_basename', _basename)
101
106
  app.instance_variable_set(:'@_app_install_dependencies', _app_install_dependencies)
102
107
  app.instance_variable_set(:'@_app_setup_dependencies', _app_setup_dependencies)
103
108
  app.instance_variable_set(:'@_artifact', Marshal.load(Marshal.dump(_artifact)))
@@ -47,15 +47,25 @@ module Dapp
47
47
 
48
48
  # Stage
49
49
  class Stage < Base
50
+ STAGES = [:from, :infra_install, :source_1_archive, :source_1, :app_install, :source_2,
51
+ :infra_setup, :source_3, :chef_cookbooks, :app_setup, :source_4, :source_5].freeze
52
+
50
53
  attr_accessor :_config
51
54
  attr_accessor :_before, :_after
52
55
 
56
+ def initialize(*args)
57
+ super
58
+ raise Error::Config, code: :stage_artifact_not_associated if _before.nil? && _after.nil?
59
+ end
60
+
53
61
  def _before=(stage)
54
62
  @_before = stage.to_sym
63
+ validate_associated_option(option: :before, value: @_before)
55
64
  end
56
65
 
57
66
  def _after=(stage)
58
67
  @_after = stage.to_sym
68
+ validate_associated_option(option: :after, value: @_after)
59
69
  end
60
70
 
61
71
  protected
@@ -63,6 +73,13 @@ module Dapp
63
73
  def code
64
74
  :artifact_unexpected_attribute
65
75
  end
76
+
77
+ private
78
+
79
+ def validate_associated_option(option:, value:)
80
+ return if STAGES.include? value
81
+ raise Error::Config, code: :stage_artifact_incorrect_associated_value, data: { option: option, value: value }
82
+ end
66
83
  end
67
84
  end
68
85
  end
@@ -8,8 +8,8 @@ module Dapp
8
8
  def initialize
9
9
  @_volume = []
10
10
  @_expose = []
11
- @_env = []
12
- @_label = []
11
+ @_env = {}
12
+ @_label = {}
13
13
  @_cmd = []
14
14
  @_onbuild = []
15
15
  end
@@ -28,11 +28,11 @@ module Dapp
28
28
  end
29
29
 
30
30
  def env(**options)
31
- @_env.concat(options_to_args(options))
31
+ @_env.merge!(options)
32
32
  end
33
33
 
34
34
  def label(**options)
35
- @_label.concat(options_to_args(options))
35
+ @_label.merge!(options)
36
36
  end
37
37
 
38
38
  def cmd(*args)
@@ -76,12 +76,6 @@ module Dapp
76
76
  def clone
77
77
  Marshal.load(Marshal.dump(self))
78
78
  end
79
-
80
- private
81
-
82
- def options_to_args(options)
83
- options.map { |key, value| "#{key.upcase}=#{value}" }
84
- end
85
79
  end
86
80
  end
87
81
  end
@@ -4,7 +4,7 @@ module Dapp
4
4
  class Main < Application
5
5
  def initialize(**options)
6
6
  @_home_path = Pathname.new(options[:dappfile_path]).parent.expand_path.to_s
7
- @_name = Pathname.new(@_home_path).basename.to_s
7
+ @_basename = Pathname.new(@_home_path).basename.to_s
8
8
  @_builder = Pathname.new(@_home_path).join('Berksfile').exist? ? :chef : :shell
9
9
 
10
10
  @_docker = Docker.new
@@ -16,7 +16,7 @@ module Dapp
16
16
  end
17
17
 
18
18
  def name(value)
19
- @_name = value
19
+ @_basename = value
20
20
  end
21
21
  end
22
22
  end
@@ -23,7 +23,12 @@ module Dapp
23
23
  end
24
24
 
25
25
  def build
26
- build_configs.each { |config| Application.new(config: config, cli_options: cli_options).build! }
26
+ build_configs.each do |config|
27
+ log_step(config._name)
28
+ with_log_indent do
29
+ Application.new(config: config, cli_options: cli_options).build!
30
+ end
31
+ end
27
32
  end
28
33
 
29
34
  def list
@@ -43,17 +48,12 @@ module Dapp
43
48
  end
44
49
  end
45
50
 
46
- def flush_metadata
47
- build_configs.each do |config|
48
- log(config._name)
49
- app = Application.new(config: config, cli_options: cli_options, ignore_git_fetch: true)
50
- FileUtils.rm_rf app.metadata_path
51
- end
51
+ def stages_flush
52
+ shellout(%{docker rmi $(docker images --format="{{.Repository}}:{{.Tag}}" #{build_configs.first._basename}-dappstage)})
52
53
  end
53
54
 
54
- def self.flush_stages
55
- shellout('docker rmi $(docker images --format="{{.Repository}}:{{.Tag}}" dapp)')
56
- shellout('docker rmi $(docker images -f "dangling=true" -q)')
55
+ def stages_cleanup
56
+ shellout(%{docker rmi $(docker images -f "dangling=true" -f "label=dapp=#{build_configs.first._basename}" -q)})
57
57
  end
58
58
 
59
59
  private
@@ -13,7 +13,7 @@ module Dapp
13
13
  data = desc[:data] || {}
14
14
  ::I18n.t [:common, context, code].join('.'), [:common, code].join('.'), **data, raise: true
15
15
  rescue ::I18n::MissingTranslationData => _e
16
- raise NetStatus::Exception, code: :missing_translation, data: { code: code }
16
+ raise ::NetStatus::Exception, code: :missing_translation, data: { code: code }
17
17
  end
18
18
  end
19
19
  end # Helper
@@ -43,6 +43,7 @@ module Dapp
43
43
  def with_log_indent(with = true)
44
44
  log_indent_next if with
45
45
  yield
46
+ ensure
46
47
  log_indent_prev if with
47
48
  end
48
49
 
@@ -10,12 +10,12 @@ module Dapp
10
10
  add_change_option(:expose, value)
11
11
  end
12
12
 
13
- def add_change_env(value)
14
- add_change_option(:env, value)
13
+ def add_change_env(**options)
14
+ add_change_option(:env, options_to_args(options))
15
15
  end
16
16
 
17
- def add_change_label(value)
18
- add_change_option(:label, value)
17
+ def add_change_label(**options)
18
+ add_change_option(:label, options_to_args(options))
19
19
  end
20
20
 
21
21
  def add_change_cmd(value)
@@ -84,6 +84,10 @@ module Dapp
84
84
  end
85
85
  end
86
86
 
87
+ def options_to_args(options)
88
+ options.map { |key, value| "#{key}=#{value}" }
89
+ end
90
+
87
91
  def prepared_options
88
92
  prepared_options_default(options) { |k, vals| Array(vals).map { |v| "--#{k}=#{v}" }.join(' ') }
89
93
  end
@@ -19,16 +19,10 @@ module Dapp
19
19
  end
20
20
 
21
21
  def build!(**kwargs)
22
- @built_id = if should_be_built?
23
- begin
24
- run!(**kwargs)
25
- commit!
26
- ensure
27
- shellout("docker rm #{container_name}")
28
- end
29
- else
30
- from.built_id
31
- end
22
+ run!(**kwargs)
23
+ @built_id = commit!
24
+ ensure
25
+ shellout("docker rm #{container_name}")
32
26
  end
33
27
 
34
28
  def export!(name, log_verbose: false, log_time: false, force: false)
@@ -65,10 +59,6 @@ module Dapp
65
59
  def commit!
66
60
  shellout!("docker commit #{prepared_change} #{container_name}").stdout.strip
67
61
  end
68
-
69
- def should_be_built?
70
- !(bash_commands.empty? && change_options.empty?)
71
- end
72
62
  end # Stage
73
63
  end # Image
74
64
  end # Dapp
@@ -1,5 +1,5 @@
1
1
  # Version
2
2
  module Dapp
3
- VERSION = '0.3.0'.freeze
3
+ VERSION = '0.3.1'.freeze
4
4
  BUILD_CACHE_VERSION = 1
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Stolyarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-04 00:00:00.000000000 Z
11
+ date: 2016-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-shellout
@@ -338,6 +338,8 @@ files:
338
338
  - lib/dapp/build/stage/from.rb
339
339
  - lib/dapp/build/stage/infra_install.rb
340
340
  - lib/dapp/build/stage/infra_setup.rb
341
+ - lib/dapp/build/stage/mod/artifact.rb
342
+ - lib/dapp/build/stage/mod/logging.rb
341
343
  - lib/dapp/build/stage/source_1.rb
342
344
  - lib/dapp/build/stage/source_1_archive.rb
343
345
  - lib/dapp/build/stage/source_2.rb
@@ -353,13 +355,13 @@ files:
353
355
  - lib/dapp/cli.rb
354
356
  - lib/dapp/cli/base.rb
355
357
  - lib/dapp/cli/build.rb
356
- - lib/dapp/cli/flush.rb
357
- - lib/dapp/cli/flush/metadata.rb
358
- - lib/dapp/cli/flush/stages.rb
359
358
  - lib/dapp/cli/list.rb
360
359
  - lib/dapp/cli/push.rb
361
360
  - lib/dapp/cli/run.rb
362
361
  - lib/dapp/cli/smartpush.rb
362
+ - lib/dapp/cli/stages.rb
363
+ - lib/dapp/cli/stages/cleanup.rb
364
+ - lib/dapp/cli/stages/flush.rb
363
365
  - lib/dapp/config/application.rb
364
366
  - lib/dapp/config/artifact.rb
365
367
  - lib/dapp/config/chef.rb