dapp 0.18.5 → 0.19.0

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