dapp 0.18.5 → 0.19.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f192d0db959cd4bbe86c8ee764de426729e292f05f8887d2540c93d79c13369
4
- data.tar.gz: c9869e3365e81c5b60ed6f7a8a6551feba1b3da8f2226afab49f5d43c18637be
3
+ metadata.gz: 2dccc0e1f4d0b7a91f69e715cf39b028b998a4872bb6835eb6ba77bee05ed991
4
+ data.tar.gz: 2ee85bb1d9906d705aabe8343982a4afc3ab0ba337875f2d031a8b53ce8eab4a
5
5
  SHA512:
6
- metadata.gz: 3379f78551bebf688b5f8b74b92832dae9970b6b479af32427e693b1a64b4b1d9f456a383a0bad1a4d0cc086d8047f33cb00e59f7a09c06ee1fa78aac2866932
7
- data.tar.gz: 72893404d6790aa820bf3b835a097fa9cca4d5f7346c3d874f0ad167114d1b79f3a397e1d38386dd127d232a0e60d06d4c28b53029deb683eaf56155d1989f48
6
+ metadata.gz: 490982b52706aae26ae42a827abf2bca667f80853ecf5a419dfbe5621b38b6d4cce2bf0e4ef703c0135182082cabb7485ecf48d7542d7189348248b1ac3d3dd9
7
+ data.tar.gz: 7aec1a9542c4f892c1f69a96884be15d4182817a8c74254450c1024db15b177ec7cb4a41c67441b41441891c35e7338f227cb4b96a6d06b8f85817890e41a1e3
@@ -50,6 +50,12 @@ module Dapp
50
50
  end
51
51
  end # << self
52
52
 
53
+ def shellout_cmd_should_succeed!(cmd)
54
+ return cmd.tap(&:error!)
55
+ rescue ::Mixlib::ShellOut::ShellCommandFailed => e
56
+ raise Error::Shellout, code: Helper::Trivia.class_to_lowercase(e.class), data: { stream: e.message }
57
+ end
58
+
53
59
  protected
54
60
 
55
61
  def _shellout_with_logging!(*args, verbose: false, quiet: true, time: false, **kwargs)
@@ -27,7 +27,7 @@ module Dapp
27
27
  no_lock = false
28
28
 
29
29
  dimg.dapp.lock("#{dimg.dapp.name}.image.#{image.name}") do
30
- image.cache_reset
30
+ image.class.reset_image_inspect(image.name)
31
31
 
32
32
  if image_should_be_locked?
33
33
  yield
@@ -187,8 +187,6 @@ module Dapp
187
187
  Dir[from_path.join('**/*')]
188
188
  .map(&Pathname.method(:new))
189
189
  .each do |from_subpath|
190
- next if from_subpath.directory?
191
-
192
190
  to_subpath = to_path.join(from_subpath.relative_path_from(from_path))
193
191
  if to_subpath.exist?
194
192
  raise(Error::Chef,
@@ -5,9 +5,7 @@ module Dapp::Dimg::CLI
5
5
  banner <<BANNER.freeze
6
6
  Usage:
7
7
 
8
- dapp dimg cleanup [options] [DIMG ...]
9
-
10
- DIMG Dapp image to process [default: *].
8
+ dapp dimg cleanup [options]
11
9
 
12
10
  Options:
13
11
  BANNER
@@ -4,16 +4,9 @@ module Dapp
4
4
  module Command
5
5
  module Cleanup
6
6
  def cleanup
7
- lock("#{name}.images") do
8
- log_step_with_indent(name) do
9
- dapp_containers_flush
10
- dapp_dangling_images_flush
11
- remove_images_by_query([
12
- "#{host_docker} images",
13
- %(--format '{{if ne "#{stage_cache}" .Repository }}{{.Repository}}:{{.Tag}}{{ end }}'),
14
- %(-f "label=dapp=#{stage_dapp_label}")
15
- ].join(' ')) # FIXME: negative filter is not currently supported by the Docker CLI
16
- end
7
+ log_step_with_indent(:cleanup) do
8
+ dapp_containers_flush
9
+ dapp_dangling_images_flush
17
10
  end
18
11
  end
19
12
  end
@@ -5,47 +5,109 @@ module Dapp
5
5
  module Common
6
6
  protected
7
7
 
8
- def dapp_images_names
9
- shellout!(%(#{host_docker} images --format="{{.Repository}}:{{.Tag}}" #{stage_cache})).stdout.lines.map(&:strip)
8
+ def dapp_project_image_labels(image_id)
9
+ dapp_project_image_inspect(image_id)['Config']['Labels']
10
10
  end
11
11
 
12
- def dapp_images_ids
13
- shellout!(%(#{host_docker} images #{stage_cache} -q --no-trunc)).stdout.lines.map(&:strip)
12
+ def dapp_project_image_inspect(image_id_or_name)
13
+ return {} unless dapp_project_image_exist?(image_id_or_name)
14
+
15
+ dapp_project_images.find { |img| [img[:name], img[:id]].include?(image_id_or_name) }[:inspect] ||= begin
16
+ cmd = shellout!("#{::Dapp::Dapp.host_docker} inspect --type=image #{image_id_or_name}")
17
+ Array(JSON.parse(cmd.stdout.strip)).first || {}
18
+ end
19
+ end
20
+
21
+ def dapp_project_image_exist?(image_id_or_name)
22
+ dapp_project_images.any? { |img| [img[:name], img[:id]].include?(image_id_or_name) }
23
+ end
24
+
25
+ def dapp_project_images_ids
26
+ dapp_project_images.map { |img| img[:id] }
27
+ end
28
+
29
+ def dapp_project_dangling_images
30
+ dapp_project_images.select { |img| project_dangling_image?(img) }
31
+ end
32
+
33
+ def project_dangling_image?(image)
34
+ image[:name] == '<none>:<none>'
35
+ end
36
+
37
+ def dapp_project_images
38
+ @dapp_project_images ||= [].tap do |images|
39
+ shellout!(%(#{host_docker} images --format="{{.ID}};{{.Repository}}:{{.Tag}};{{.CreatedAt}}" -f "label=dapp" #{stage_cache} --no-trunc))
40
+ .stdout
41
+ .lines
42
+ .map(&:strip)
43
+ .each do |l|
44
+ id, name, created_at = l.split(';')
45
+ images << { id: id, name: name, created_at: Time.parse(created_at) }
46
+ end
47
+ end
48
+ end
49
+
50
+ def dapp_project_containers_flush
51
+ remove_containers_by_query(%(#{host_docker} ps -a -f "label=dapp" -f "name=#{container_name_prefix}" -q --no-trunc))
52
+ end
53
+
54
+ def dapp_project_dangling_images_flush
55
+ remove_project_images(dapp_project_dangling_images.map { |img| img[:id] })
56
+ end
57
+
58
+ def remove_project_images(images_ids_or_names)
59
+ images_ids_or_names = convert_to_project_images_names(images_ids_or_names)
60
+ update_project_images(images_ids_or_names)
61
+ remove_images(images_ids_or_names)
62
+ end
63
+
64
+ def update_project_images(images_ids_or_names)
65
+ dapp_project_images.delete_if do |img|
66
+ images_ids_or_names.include?(img[:id]) || images_ids_or_names.include?(img[:name])
67
+ end
68
+ end
69
+
70
+ def convert_to_project_images_names(images_ids_or_names)
71
+ dapp_project_images.each_with_object([]) do |image, images|
72
+ if images_ids_or_names.include?(image[:id]) || images_ids_or_names.include?(image[:name])
73
+ images << (project_dangling_image?(image) ? image[:id] : image[:name])
74
+ end
75
+ end
14
76
  end
15
77
 
16
78
  def dapp_containers_flush
17
- remove_containers_by_query(%(#{host_docker} ps -a -f "label=dapp" -f "name=#{container_name_prefix}" -q), force: true)
79
+ remove_containers_by_query(%(#{host_docker} ps -a -f "label=dapp" -q --no-trunc))
18
80
  end
19
81
 
20
82
  def dapp_dangling_images_flush
21
- remove_images_by_query(%(#{host_docker} images -f "dangling=true" -f "label=dapp=#{stage_dapp_label}" -q), force: true)
83
+ remove_images_by_query(%(#{host_docker} images -f "dangling=true" -f "label=dapp" -q --no-trunc))
22
84
  end
23
85
 
24
- def remove_images_by_query(images_query, force: false)
25
- with_subquery(images_query) { |ids| remove_images(ids, force: force) }
86
+ def remove_images_by_query(images_query)
87
+ with_subquery(images_query) { |ids| remove_images(ids) }
26
88
  end
27
89
 
28
- def remove_images(ids, force: false)
29
- ids.uniq!
30
- check_user_containers!(ids) unless force
31
- remove_base("#{host_docker} rmi%{force_option} %{ids}", ids, force: force)
90
+ def remove_images(images_ids_or_names)
91
+ images_ids_or_names.uniq!
92
+ check_user_containers!(images_ids_or_names)
93
+ remove_base("#{host_docker} rmi%{force_option} %{ids}", images_ids_or_names, force: false)
32
94
  end
33
95
 
34
96
  def check_user_containers!(images_ids)
35
97
  return if images_ids.empty?
36
98
  log_step_with_indent(:'check user containers') do
37
- run_command(%(#{host_docker} ps -a -q #{images_ids.uniq.map { |image_id| "--filter=ancestor=#{image_id}" }.join(' ')})).tap do |res|
99
+ run_command(%(#{host_docker} ps -a -q #{images_ids.uniq.map { |image_id| "--filter=ancestor=#{image_id}" }.join(' ')} --no-trunc)).tap do |res|
38
100
  raise Error::Command, code: :user_containers_detected, data: { ids: res.stdout.strip } if res && !res.stdout.strip.empty? && !dry_run?
39
101
  end
40
102
  end
41
103
  end
42
104
 
43
- def remove_containers_by_query(containers_query, force: false)
44
- with_subquery(containers_query) { |ids| remove_containers(ids, force: force) }
105
+ def remove_containers_by_query(containers_query)
106
+ with_subquery(containers_query) { |ids| remove_containers(ids) }
45
107
  end
46
108
 
47
- def remove_containers(ids, force: false)
48
- remove_base("#{host_docker} rm%{force_option} %{ids}", ids.uniq, force: force)
109
+ def remove_containers(ids)
110
+ remove_base("#{host_docker} rm%{force_option} %{ids}", ids.uniq, force: true)
49
111
  end
50
112
 
51
113
  def remove_base(query_format, ids, force: false)
@@ -59,10 +121,6 @@ module Dapp
59
121
  yield(res)
60
122
  end
61
123
 
62
- def image_labels(image_id)
63
- Image::Stage.image_config_option(image_id: image_id, option: 'Labels') || {}
64
- end
65
-
66
124
  def run_command(cmd)
67
125
  log(cmd) if log_verbose? || dry_run?
68
126
  shellout!(cmd) unless dry_run?
@@ -6,36 +6,25 @@ module Dapp
6
6
  # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
7
7
  def mrproper
8
8
  log_step_with_indent(:mrproper) do
9
- raise Error::Command, code: :mrproper_required_option unless proper_all? || proper_dev_mode_cache? || proper_cache_version?
10
-
11
- dapp_dangling_images_flush
9
+ raise Error::Command, code: :mrproper_required_option if mrproper_command_without_any_option?
12
10
 
13
11
  if proper_all?
14
- flush_by_label('dapp')
15
- remove_build_dir
12
+ proper_all
16
13
  elsif proper_dev_mode_cache?
17
- flush_by_label('dapp-dev-mode')
14
+ proper_dev_mode_cache
18
15
  elsif proper_cache_version?
19
- log_proper_cache do
20
- proper_cache_images = proper_cache_all_images
21
- remove_images(dapp_images_by_label('dapp').select { |id| !proper_cache_images.include?(id) }.map(&:strip))
22
- end
16
+ proper_cache_version
23
17
  end
18
+
19
+ dapp_dangling_images_flush
24
20
  end
25
21
  end
26
22
  # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
27
23
 
28
24
  protected
29
25
 
30
- def flush_by_label(label)
31
- log_step_with_indent(:containers) { dapp_containers_flush_by_label(label) }
32
- log_step_with_indent(:images) { dapp_images_flush_by_label(label) }
33
- end
34
-
35
- def remove_build_dir
36
- log_step_with_indent(:build_dir) { FileUtils.rm_rf(build_path) }
37
- rescue ::Dapp::Error::Dapp => e
38
- raise unless e.net_status[:code] == :dappfile_not_found
26
+ def mrproper_command_without_any_option?
27
+ !(proper_all? || proper_dev_mode_cache? || proper_cache_version?)
39
28
  end
40
29
 
41
30
  def proper_all?
@@ -46,34 +35,54 @@ module Dapp
46
35
  !!options[:proper_dev_mode_cache]
47
36
  end
48
37
 
49
- def dapp_containers_flush_by_label(label)
50
- remove_containers_by_query(%(#{host_docker} ps -a -f "label=#{label}" -q), force: true)
38
+ def proper_all
39
+ flush_by_label('dapp')
40
+ remove_build_dir
51
41
  end
52
42
 
53
- def dapp_dangling_images_flush_by_label(label)
54
- remove_images_by_query(%(#{host_docker} images -f "dangling=true" -f "label=#{label}" -q), force: true)
43
+ def remove_build_dir
44
+ build_path.tap { |p| log_step_with_indent(:build_dir) { FileUtils.rm_rf(p) } }
45
+ rescue ::Dapp::Error::Dapp => e
46
+ raise unless e.net_status[:code] == :dappfile_not_found
47
+ end
48
+
49
+ def proper_dev_mode_cache
50
+ flush_by_label('dapp-dev-mode')
51
+ end
52
+
53
+ def flush_by_label(label)
54
+ log_step_with_indent(:containers) { dapp_containers_flush_by_label(label) }
55
+ log_step_with_indent(:images) { dapp_images_flush_by_label(label) }
56
+ end
57
+
58
+ def dapp_containers_flush_by_label(label)
59
+ remove_containers_by_query(%(#{host_docker} ps -a -f "label=dapp" -f "label=#{label}" -q --no-trunc))
55
60
  end
56
61
 
57
62
  def dapp_images_flush_by_label(label)
58
- dapp_dangling_images_flush_by_label(label)
59
- remove_images(dapp_images_by_label(label), force: true)
63
+ remove_images(dapp_images_names_by_label(label))
60
64
  end
61
65
 
62
- def dapp_images_by_label(label)
63
- @dapp_images ||= begin
64
- shellout!(%(#{host_docker} images -f "dangling=false" --format="{{.Repository}}:{{.Tag}}" -f "label=#{label}"))
65
- .stdout
66
- .lines
67
- .map(&:strip)
66
+ def proper_cache_version
67
+ log_proper_cache do
68
+ proper_cache_all_images_names.tap do |proper_cache_images|
69
+ remove_images(dapp_images_names_by_label('dapp').select { |image_name| !proper_cache_images.include?(image_name) })
70
+ end
68
71
  end
69
72
  end
70
73
 
71
- def proper_cache_all_images
72
- shellout!([
73
- "#{host_docker} images",
74
- '--format="{{.Repository}}:{{.Tag}}"',
75
- %(-f "label=dapp-cache-version=#{::Dapp::BUILD_CACHE_VERSION}" -f "dangling=false")
76
- ].join(' ')).stdout.lines.map(&:strip)
74
+ def proper_cache_all_images_names
75
+ shellout!(%(#{host_docker} images --format="{{.Repository}}:{{.Tag}}" -f "dangling=false" -f "label=dapp" -f "label=dapp-cache-version=#{::Dapp::BUILD_CACHE_VERSION}"))
76
+ .stdout
77
+ .lines
78
+ .map(&:strip)
79
+ end
80
+
81
+ def dapp_images_names_by_label(label)
82
+ shellout!(%(#{host_docker} images --format="{{.Repository}}:{{.Tag}}" -f "dangling=false" -f "label=dapp" -f "label=#{label}"))
83
+ .stdout
84
+ .lines
85
+ .map(&:strip)
77
86
  end
78
87
  end
79
88
  end
@@ -8,7 +8,7 @@ module Dapp
8
8
  lock_repo(option_repo, readonly: true) do
9
9
  raise Error::Command, code: :stages_cleanup_required_option unless stages_cleanup_option?
10
10
 
11
- dapp_containers_flush
11
+ dapp_project_containers_flush
12
12
 
13
13
  proper_cache if proper_cache_version?
14
14
  stages_cleanup_by_repo if proper_repo_cache?
@@ -22,121 +22,95 @@ module Dapp
22
22
  log_proper_cache do
23
23
  lock("#{name}.images") do
24
24
  log_step_with_indent(name) do
25
- remove_images(dapp_images_names.select { |image_name| !actual_cache_images.include?(image_name) })
25
+ remove_project_images(dapp_project_images_ids.select { |image_id| !actual_cache_project_images_ids.include?(image_id) })
26
26
  end
27
27
  end
28
28
  end
29
29
  end
30
30
 
31
+ def actual_cache_project_images_ids
32
+ @actual_cache_project_images_ids ||= begin
33
+ shellout!(%(#{host_docker} images -f "label=dapp" -f "label=dapp-cache-version=#{::Dapp::BUILD_CACHE_VERSION}" #{stage_cache} -q --no-trunc))
34
+ .stdout
35
+ .lines
36
+ .map(&:strip)
37
+ end
38
+ end
39
+
31
40
  def stages_cleanup_by_repo
32
41
  registry = registry(option_repo)
33
42
  repo_dimgs = repo_dimgs_images(registry)
34
43
 
35
44
  lock("#{name}.images") do
36
45
  log_step_with_indent(name) do
37
- dapp_dangling_images_flush
38
- dimgs, stages = dapp_images_hash.partition { |_, image_spec| repo_dimgs.values.include?(image_spec[:id]) }.map(&:to_h)
39
- dimgs.each { |_, dimg_spec| except_image_with_parents(dimg_spec[:id], stages) }
46
+ dapp_project_dangling_images_flush
47
+
48
+ dimgs, stages = dapp_project_images.partition { |image| repo_dimgs.values.include?(image[:id]) }
49
+ dimgs.each { |dimg_image| except_dapp_project_image_with_parents(dimg_image[:id], stages) }
40
50
 
41
51
  # Удаление только образов старше 2ч
42
- stages.delete_if do |_, stage_spec|
43
- Time.now - stage_spec[:created_at] < 2*60*60
52
+ stages.delete_if do |stage_image|
53
+ Time.now - stage_image[:created_at] < 2*60*60
44
54
  end
45
55
 
46
- remove_images(stages.keys)
56
+ remove_project_images(stages.map { |image| image[:id]} )
47
57
  end
48
58
  end
49
59
  end
50
60
 
51
- def repo_dimgs_images(registry)
52
- repo_dimgs_and_cache(registry).first
53
- end
54
-
55
- def actual_cache_images
56
- @actual_cache_images ||= begin
57
- shellout!([
58
- "#{host_docker} images",
59
- '--format="{{.Repository}}:{{.Tag}}"',
60
- %(-f "label=dapp-cache-version=#{::Dapp::BUILD_CACHE_VERSION}"),
61
- stage_cache
62
- ].join(' ')).stdout.lines.map(&:strip)
63
- end
64
- end
65
-
66
- def dapp_images_hash
67
- shellout!(%(#{host_docker} images --format "{{.Repository}}:{{.Tag}};{{.ID}};{{.CreatedAt}}" --no-trunc #{stage_cache}))
68
- .stdout.lines.map do |line|
69
- name, id, created_at = line.strip.split(';', 3)
70
- [name, {name: name, id: id, created_at: Time.parse(created_at)}]
71
- end.to_h
72
- end
73
-
74
- def except_image_with_parents(image_id, stages)
75
- if image_exist?(image_id)
76
- image_dapp_artifacts_label(image_id).each { |aiid| except_image_with_parents(aiid, stages) }
61
+ def except_dapp_project_image_with_parents(image_id, stages)
62
+ if dapp_project_image_exist?(image_id)
63
+ dapp_project_image_artifacts_ids_in_labels(image_id).each { |aiid| except_dapp_project_image_with_parents(aiid, stages) }
77
64
  iid = image_id
78
65
  loop do
79
- stages.delete_if { |_, stage_spec| stage_spec[:id] == iid }
80
- break if (iid = image_parent(iid)).empty?
66
+ stages.delete_if { |stage_image| stage_image[:id] == iid }
67
+ break if (iid = dapp_project_image_parent_id(iid)).nil?
81
68
  end
82
69
  else
83
- stages.delete_if { |_, stage_spec| stage_spec[:id] == image_id }
70
+ stages.delete_if { |stage_image| stage_image[:id] == image_id }
84
71
  end
85
72
  end
86
73
 
87
- def image_exist?(image_id)
88
- shellout!(%(#{host_docker} inspect #{image_id}))
89
- true
90
- rescue ::Dapp::Error::Shellout
91
- false
92
- end
93
-
94
- def image_dapp_artifacts_label(image_id)
95
- select_dapp_artifacts_ids(::Dapp::Dimg::Image::Docker.image_config_option(image_id: image_id, option: 'Labels') || {})
96
- end
97
-
98
- def image_parent(image_id)
99
- shellout!(%(#{host_docker} inspect -f {{.Parent}} #{image_id})).stdout.strip
74
+ def dapp_project_image_artifacts_ids_in_labels(image_id)
75
+ select_dapp_artifacts_ids(dapp_project_image_labels(image_id))
100
76
  end
101
77
 
102
78
  def proper_git_commit
103
79
  log_proper_git_commit do
104
- unproper_images_names = []
105
- dapp_images_detailed.each do |_, attrs|
106
- attrs['Config']['Labels'].each do |repo_name, commit|
107
- next if (repo = dapp_git_repositories[repo_name]).nil?
108
- unproper_images_names.concat(image_hierarchy_by_id(attrs['Id'])) unless repo.commit_exists?(commit)
109
- end
110
- end
111
- remove_images(unproper_images_names.uniq)
112
- end
113
- end
114
-
115
- def dapp_images_detailed
116
- @dapp_images_detailed ||= {}.tap do |images|
117
- dapp_images_names.each do |image_name|
118
- shellout!(%(#{host_docker} inspect --format='{{json .}}' #{image_name})).stdout.strip.tap do |output|
119
- images[image_name] = output == 'null' ? {} : JSON.parse(output)
80
+ lock("#{name}.images") do
81
+ dapp_project_dangling_images_flush
82
+
83
+ unproper_images_ids = []
84
+ dapp_project_images_ids.each do |image_id|
85
+ dapp_project_image_labels(image_id).each do |repo_name, commit|
86
+ next if (repo = dapp_git_repositories[repo_name]).nil?
87
+ unproper_images_ids.concat(dapp_project_image_hierarchy(image_id)) unless repo.commit_exists?(commit)
88
+ end
120
89
  end
90
+ remove_project_images(unproper_images_ids)
121
91
  end
122
92
  end
123
93
  end
124
94
 
125
- def image_hierarchy_by_id(image_id)
95
+ def dapp_project_image_hierarchy(image_id)
126
96
  hierarchy = []
127
97
  iids = [image_id]
128
98
 
129
99
  loop do
130
- hierarchy.concat(dapp_images_detailed.map { |name, attrs| name if iids.include?(attrs['Id']) }.compact)
100
+ hierarchy.concat(dapp_project_images_ids.select { |image_id| iids.include?(image_id) })
131
101
  break if begin
132
102
  iids.map! do |iid|
133
- dapp_images_detailed.map { |_, attrs| attrs['Id'] if attrs['Parent'] == iid }.compact
103
+ dapp_project_images_ids.select { |image_id| dapp_project_image_parent_id(image_id) == iid }
134
104
  end.flatten!.empty?
135
105
  end
136
106
  end
137
107
 
138
108
  hierarchy
139
109
  end
110
+
111
+ def dapp_project_image_parent_id(image_id)
112
+ dapp_project_image_inspect(image_id)['Parent']
113
+ end
140
114
  end
141
115
  end
142
116
  end
@@ -8,8 +8,10 @@ module Dapp
8
8
  lock_repo(repo = option_repo) do
9
9
  raise Error::Command, code: :stages_cleanup_required_option unless stages_cleanup_option?
10
10
 
11
- registry = registry(repo)
12
- repo_dimgs, repo_stages = repo_dimgs_and_cache(registry)
11
+ registry = registry(repo)
12
+ repo_dimgs = repo_dimgs_images(registry)
13
+ repo_stages = repo_stages_images(registry)
14
+
13
15
  repo_stages.delete_if { |_, siid| repo_dimgs.values.include?(siid) } # ignoring stages with dimgs ids (v2)
14
16
 
15
17
  proper_repo_cache(registry, repo_stages) if proper_cache_version?
@@ -31,7 +33,7 @@ module Dapp
31
33
  end
32
34
 
33
35
  def repo_stages_cleanup(registry, repo_dimgs, repo_stages)
34
- log_step_with_indent(repo) do
36
+ log_step_with_indent(option_repo) do
35
37
  repo_dimgs.each { |image_tag, image_id| clear_repo_stages(registry, repo_stages, image_tag, image_id) }
36
38
  repo_stages.keys.each { |image_tag| delete_repo_image(registry, image_tag) }
37
39
  end
@@ -79,7 +81,7 @@ module Dapp
79
81
  end
80
82
 
81
83
  def repo_dapp_dappstage_images_detailed(registry)
82
- @repo_dapp_images_detailed ||= begin
84
+ @repo_dapp_dappstage_images_detailed ||= begin
83
85
  registry.tags.map do |tag|
84
86
  next unless tag.start_with?('dimgstage')
85
87
 
@@ -11,18 +11,30 @@ module Dapp
11
11
  ::Dapp::Dimg::DockerRegistry.new(repo)
12
12
  end
13
13
 
14
- def repo_dimgs_and_cache(registry)
15
- format = proc do |arr|
16
- arr.map do |tag|
17
- if (id = registry.image_id(tag)).nil?
18
- log_warning(desc: { code: 'tag_ignored', data: { tag: tag } })
19
- else
20
- [tag, id]
21
- end
22
- end.compact.to_h
14
+ def repo_dimgs_images(registry)
15
+ repo_dimgs_and_stages_images(registry)[:dimgs]
16
+ end
17
+
18
+ def repo_stages_images(registry)
19
+ repo_dimgs_and_stages_images(registry)[:stages]
20
+ end
21
+
22
+ def repo_dimgs_and_stages_images(registry)
23
+ @repo_dimgs_and_cache_names ||= {}.tap do |images|
24
+ format = proc do |arr|
25
+ arr.map do |tag|
26
+ if (id = registry.image_id(tag)).nil?
27
+ log_warning(desc: { code: 'tag_ignored', data: { tag: tag } })
28
+ else
29
+ [tag, id]
30
+ end
31
+ end.compact.to_h
32
+ end
33
+ dimgs, stages = registry_tags(registry).partition { |tag| !tag.start_with?('dimgstage') }
34
+
35
+ images[:dimgs] = format.call(dimgs)
36
+ images[:stages] = format.call(stages)
23
37
  end
24
- dimgs, stages = registry.tags.partition { |tag| !tag.start_with?('dimgstage') }
25
- [format.call(dimgs), format.call(stages)]
26
38
  end
27
39
 
28
40
  def registry_tags(registry)
@@ -41,8 +53,8 @@ module Dapp
41
53
  end
42
54
  end
43
55
 
44
- def select_dapp_artifacts_ids(hash)
45
- hash.select { |k, _v| k.start_with?('dapp-artifact') }.values
56
+ def select_dapp_artifacts_ids(labels)
57
+ labels.select { |k, _v| k.start_with?('dapp-artifact') }.values
46
58
  end
47
59
 
48
60
  def dapp_git_repositories
@@ -7,9 +7,9 @@ module Dapp
7
7
  def stages_flush_local
8
8
  lock("#{name}.images") do
9
9
  log_step_with_indent(name) do
10
- dapp_containers_flush
11
- dapp_dangling_images_flush
12
- remove_images(dapp_images_names)
10
+ dapp_project_containers_flush
11
+ dapp_project_dangling_images_flush
12
+ remove_project_images(dapp_project_images_ids)
13
13
  end
14
14
  end
15
15
  end
@@ -7,8 +7,10 @@ module Dapp
7
7
  def stages_flush_repo
8
8
  lock_repo(option_repo) do
9
9
  log_step_with_indent(option_repo) do
10
- registry = registry(option_repo)
11
- repo_dimgs, repo_stages = repo_dimgs_and_cache(registry)
10
+ registry = registry(option_repo)
11
+ repo_dimgs = repo_dimgs_images(registry)
12
+ repo_stages = repo_stages_images(registry)
13
+
12
14
  repo_dimgs.merge(repo_stages).keys.each { |image_tag| delete_repo_image(registry, image_tag) }
13
15
  end
14
16
  end
@@ -83,7 +83,8 @@ module Dapp
83
83
  dapp.log_state(image_name, state: dapp.t(code: 'state.push'), styles: { status: :success })
84
84
  else
85
85
  dapp.lock("image.#{hashsum image_name}") do
86
- ::Dapp::Dimg::Image::Stage.cache.delete(image_name)
86
+ ::Dapp::Dimg::Image::Docker.reset_image_inspect(image_name)
87
+
87
88
  dapp.log_process(image_name, process: dapp.t(code: 'status.process.pushing')) do
88
89
  image.export!(image_name)
89
90
  end
@@ -97,7 +98,8 @@ module Dapp
97
98
  begin
98
99
  image_name = format(format, repo: repo, signature: image.name.split(':').last)
99
100
  import_base!(image, image_name)
100
- rescue ::Dapp::Error::Shellout
101
+ rescue ::Dapp::Error::Shellout => e
102
+ dapp.log_info ::Dapp::Helper::NetStatus.message(e)
101
103
  next
102
104
  end
103
105
  break unless dapp.pull_all_stages?
@@ -25,9 +25,9 @@ module Dapp
25
25
  # FIXME: Лучше сейчас убрать фильтрацию, а добавить ее когда наберется достаточно
26
26
  # FIXME: примеров использования.
27
27
 
28
- def patches(from, to, exclude_paths: [], **kwargs)
28
+ def patches(from, to, paths: [], exclude_paths: [], **kwargs)
29
29
  diff(from, to, **kwargs).patches.select do |patch|
30
- !exclude_paths.any? { |p| check_path?(patch.delta.new_file[:path], p) }
30
+ !ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
31
31
  end
32
32
  end
33
33
 
@@ -35,15 +35,7 @@ module Dapp
35
35
  [].tap do |entries|
36
36
  lookup_commit(commit).tree.walk(:preorder) do |root, entry|
37
37
  fullpath = File.join(root, entry[:name]).reverse.chomp('/').reverse
38
-
39
- is_exclude_path = exclude_paths.any? { |p| check_path?(fullpath, p) }
40
- is_include_path = begin
41
- paths.empty? ||
42
- paths.any? { |p| check_path?(fullpath, p) || check_subpath?(fullpath, p) }
43
- end
44
-
45
- next false if is_exclude_path || !is_include_path
46
-
38
+ next if entry[:type] == :tree || ignore_path?(fullpath, paths: paths, exclude_paths: exclude_paths)
47
39
  entries << [root, entry]
48
40
  end
49
41
  end
@@ -106,25 +98,23 @@ module Dapp
106
98
 
107
99
  private
108
100
 
109
- def check_path?(path, format)
110
- path_checker(path) do |checking_path|
111
- File.fnmatch(format, checking_path)
101
+ def ignore_path?(path, paths: [], exclude_paths: [])
102
+ is_exclude_path = exclude_paths.any? { |p| check_path?(path, p) }
103
+ is_include_path = begin
104
+ paths.empty? ||
105
+ paths.any? { |p| File.fnmatch?(p, path) || File.fnmatch?(File.join(p, '**'), path) }
112
106
  end
113
- end
114
107
 
115
- def check_subpath?(path, format)
116
- path_checker(format) do |checking_path|
117
- File.fnmatch(checking_path, path)
118
- end
108
+ is_exclude_path || !is_include_path
119
109
  end
120
110
 
121
- def path_checker(path)
111
+ def check_path?(path, format)
122
112
  path_parts = path.split('/')
123
113
  checking_path = nil
124
114
 
125
115
  until path_parts.empty?
126
116
  checking_path = [checking_path, path_parts.shift].compact.join('/')
127
- return true if yield checking_path
117
+ return true if File.fnmatch(format, checking_path)
128
118
  end
129
119
  false
130
120
  end
@@ -16,7 +16,7 @@ module Dapp
16
16
  end
17
17
 
18
18
  Rugged::Repository.clone_at(url, path.to_s, bare: true, credentials: _rugged_credentials)
19
- rescue Rugged::NetworkError, Rugged::SslError => e
19
+ rescue Rugged::NetworkError, Rugged::SslError, Rugged::OSError => e
20
20
  raise Error::Rugged, code: :rugged_remote_error, data: { message: e.message, url: url }
21
21
  end
22
22
  end unless path.directory?
@@ -27,14 +27,13 @@ module Dapp
27
27
  end
28
28
 
29
29
  def id
30
- cache[:id]
30
+ self.class.image_inspect(self.name)["Id"]
31
31
  end
32
32
 
33
33
  def untag!
34
34
  raise Error::Build, code: :image_already_untagged, data: { name: name } unless tagged?
35
35
  dapp.shellout!("#{dapp.host_docker} rmi #{name}")
36
- self.class.image_config_delete(id)
37
- self.class.cache.delete(name)
36
+ self.class.reset_image_inspect(self.name)
38
37
  end
39
38
 
40
39
  def push!
@@ -49,21 +48,22 @@ module Dapp
49
48
  dapp.log_secondary_process(dapp.t(code: 'process.image_pull', data: { name: name })) do
50
49
  dapp.shellout!("#{dapp.host_docker} pull #{name}", verbose: true)
51
50
  end
52
- cache_reset
51
+
52
+ self.class.reset_image_inspect(self.name)
53
53
  end
54
54
 
55
55
  def tagged?
56
- !!id
56
+ not self.class.image_inspect(self.name).empty?
57
57
  end
58
58
 
59
59
  def created_at
60
60
  raise Error::Build, code: :image_not_exist, data: { name: name } unless tagged?
61
- cache[:created_at]
61
+ self.class.image_inspect(self.name)["Created"]
62
62
  end
63
63
 
64
64
  def size
65
65
  raise Error::Build, code: :image_not_exist, data: { name: name } unless tagged?
66
- cache[:size]
66
+ Float(self.class.image_inspect(self.name)["Size"])
67
67
  end
68
68
 
69
69
  def config_option(option)
@@ -71,37 +71,42 @@ module Dapp
71
71
  self.class.image_config_option(image_id: built_id, option: option)
72
72
  end
73
73
 
74
- def cache_reset
75
- self.class.cache_reset(name)
76
- end
77
-
78
74
  class << self
79
- def image_config(image_id)
80
- image_configs[image_id] ||= begin
81
- output = ::Dapp::Dapp.shellout!("#{::Dapp::Dapp.host_docker} inspect --format='{{json .Config}}' #{image_id}").stdout.strip
82
- JSON.parse(output)
75
+ def image_inspect(image_id)
76
+ image_inspects[image_id] ||= begin
77
+ cmd = ::Dapp::Dapp.shellout("#{::Dapp::Dapp.host_docker} inspect --type=image #{image_id}")
78
+
79
+ if cmd.exitstatus != 0
80
+ if cmd.stderr.start_with? "Error: No such image:"
81
+ {}
82
+ else
83
+ ::Dapp::Dapp.shellout_cmd_should_succeed! cmd
84
+ end
85
+ else
86
+ Array(JSON.parse(cmd.stdout.strip)).first || {}
87
+ end
83
88
  end
84
89
  end
85
90
 
91
+ def image_config(image_id)
92
+ image_inspect(image_id)["Config"] || {}
93
+ end
94
+
86
95
  def image_config_option(image_id:, option:)
87
96
  image_config(image_id)[option]
88
97
  end
89
98
 
90
- def image_config_delete(image_id)
91
- image_configs.delete(image_id)
99
+ def reset_image_inspect(image_id)
100
+ image_inspects.delete(image_id)
92
101
  end
93
102
 
94
- def image_configs
95
- @image_configs ||= {}
103
+ def image_inspects
104
+ @image_inspects ||= {}
96
105
  end
97
106
  end
98
107
 
99
108
  protected
100
109
 
101
- def cache
102
- self.class.cache[name.to_s] || {}
103
- end
104
-
105
110
  class << self
106
111
  def image_name_format
107
112
  "#{DockerRegistry.repo_name_format}(:(?<tag>#{tag_format}))?"
@@ -121,12 +126,7 @@ module Dapp
121
126
 
122
127
  def tag!(id:, tag:, verbose: false, quiet: false)
123
128
  ::Dapp::Dapp.shellout!("#{::Dapp::Dapp.host_docker} tag #{id} #{tag}", verbose: verbose, quiet: quiet)
124
-
125
- if cache_entry = cache.values.find {|v| v[:id] == id}
126
- cache[tag] = cache_entry
127
- else
128
- cache_reset
129
- end
129
+ image_inspects[tag] = image_inspect(id)
130
130
  end
131
131
 
132
132
  def save!(image_or_images, file_path, verbose: false, quiet: false)
@@ -137,43 +137,6 @@ module Dapp
137
137
  def load!(file_path, verbose: false, quiet: false)
138
138
  ::Dapp::Dapp.shellout!("#{::Dapp::Dapp.host_docker} load -i #{file_path}", verbose: verbose, quiet: quiet)
139
139
  end
140
-
141
- def cache
142
- @cache ||= (@cache = {}).tap { cache_reset }
143
- end
144
-
145
- def cache_reset(name = '')
146
- # FIXME: rework images cache, then delete time measure
147
- #t = Time.now
148
- cache.delete(name)
149
- ::Dapp::Dapp.shellout!("#{::Dapp::Dapp.host_docker} images --format='{{.Repository}}:{{.Tag}};{{.ID}};{{.CreatedAt}};{{.Size}}' --no-trunc #{name}")
150
- .stdout
151
- .lines
152
- .each do |l|
153
- name, id, created_at, size_field = l.split(';').map(&:strip)
154
- name = name.reverse.chomp('docker.io/'.reverse).reverse
155
- size = begin
156
- match = size_field.match(/^(\S*\d)\ ?(b|kb|mb|gb|tb)$/i)
157
- raise Error::Build, code: :unsupported_docker_image_size_format, data: {value: size_field} unless match and match[1] and match[2]
158
-
159
- number = match[1].to_f
160
- unit = match[2].downcase
161
-
162
- coef = case unit
163
- when 'b' then 0
164
- when 'kb' then 1
165
- when 'mb' then 2
166
- when 'gb' then 3
167
- when 'tb' then 4
168
- end
169
-
170
- number * (1000**coef)
171
- end
172
- cache[name] = { id: id, created_at: created_at, size: size }
173
- image_config_delete(id)
174
- end
175
- #p [:cache_reset, name, :took, Time.now - t]
176
- end
177
140
  end
178
141
  end # Docker
179
142
  end # Image
@@ -1,4 +1,4 @@
1
1
  module Dapp
2
- VERSION = '0.18.5'.freeze
3
- BUILD_CACHE_VERSION = 20
2
+ VERSION = '0.19.0'.freeze
3
+ BUILD_CACHE_VERSION = 21
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.5
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Stolyarov