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 +4 -4
- data/lib/dapp/dapp/shellout/base.rb +6 -0
- data/lib/dapp/dimg/build/stage/base.rb +1 -1
- data/lib/dapp/dimg/builder/chef/cookbook.rb +0 -2
- data/lib/dapp/dimg/cli/command/dimg/cleanup.rb +1 -3
- data/lib/dapp/dimg/dapp/command/cleanup.rb +3 -10
- data/lib/dapp/dimg/dapp/command/common.rb +79 -21
- data/lib/dapp/dimg/dapp/command/mrproper.rb +46 -37
- data/lib/dapp/dimg/dapp/command/stages/cleanup_local.rb +43 -69
- data/lib/dapp/dimg/dapp/command/stages/cleanup_repo.rb +6 -4
- data/lib/dapp/dimg/dapp/command/stages/common.rb +25 -13
- data/lib/dapp/dimg/dapp/command/stages/flush_local.rb +3 -3
- data/lib/dapp/dimg/dapp/command/stages/flush_repo.rb +4 -2
- data/lib/dapp/dimg/dimg.rb +4 -2
- data/lib/dapp/dimg/git_repo/base.rb +11 -21
- data/lib/dapp/dimg/git_repo/remote.rb +1 -1
- data/lib/dapp/dimg/image/docker.rb +29 -66
- data/lib/dapp/version.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dccc0e1f4d0b7a91f69e715cf39b028b998a4872bb6835eb6ba77bee05ed991
|
4
|
+
data.tar.gz: 2ee85bb1d9906d705aabe8343982a4afc3ab0ba337875f2d031a8b53ce8eab4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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)
|
@@ -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,
|
@@ -4,16 +4,9 @@ module Dapp
|
|
4
4
|
module Command
|
5
5
|
module Cleanup
|
6
6
|
def cleanup
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
9
|
-
|
8
|
+
def dapp_project_image_labels(image_id)
|
9
|
+
dapp_project_image_inspect(image_id)['Config']['Labels']
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
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" -
|
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
|
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
|
25
|
-
with_subquery(images_query) { |ids| remove_images(ids
|
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(
|
29
|
-
|
30
|
-
check_user_containers!(
|
31
|
-
remove_base("#{host_docker} rmi%{force_option} %{ids}",
|
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
|
44
|
-
with_subquery(containers_query) { |ids| remove_containers(ids
|
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
|
48
|
-
remove_base("#{host_docker} rm%{force_option} %{ids}", ids.uniq, 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
|
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
|
-
|
15
|
-
remove_build_dir
|
12
|
+
proper_all
|
16
13
|
elsif proper_dev_mode_cache?
|
17
|
-
|
14
|
+
proper_dev_mode_cache
|
18
15
|
elsif proper_cache_version?
|
19
|
-
|
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
|
31
|
-
|
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
|
50
|
-
|
38
|
+
def proper_all
|
39
|
+
flush_by_label('dapp')
|
40
|
+
remove_build_dir
|
51
41
|
end
|
52
42
|
|
53
|
-
def
|
54
|
-
|
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
|
-
|
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
|
63
|
-
|
64
|
-
|
65
|
-
.
|
66
|
-
|
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
|
72
|
-
shellout!(
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
38
|
-
|
39
|
-
dimgs.
|
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 |
|
43
|
-
Time.now -
|
52
|
+
stages.delete_if do |stage_image|
|
53
|
+
Time.now - stage_image[:created_at] < 2*60*60
|
44
54
|
end
|
45
55
|
|
46
|
-
|
56
|
+
remove_project_images(stages.map { |image| image[:id]} )
|
47
57
|
end
|
48
58
|
end
|
49
59
|
end
|
50
60
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
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 { |
|
80
|
-
break if (iid =
|
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 { |
|
70
|
+
stages.delete_if { |stage_image| stage_image[:id] == image_id }
|
84
71
|
end
|
85
72
|
end
|
86
73
|
|
87
|
-
def
|
88
|
-
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
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(
|
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
|
-
|
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
|
12
|
-
repo_dimgs
|
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(
|
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
|
-
@
|
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
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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(
|
45
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
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
|
11
|
-
repo_dimgs
|
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
|
data/lib/dapp/dimg/dimg.rb
CHANGED
@@ -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::
|
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
|
-
!
|
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
|
110
|
-
|
111
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
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.
|
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
|
-
|
51
|
+
|
52
|
+
self.class.reset_image_inspect(self.name)
|
53
53
|
end
|
54
54
|
|
55
55
|
def tagged?
|
56
|
-
|
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
|
-
|
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
|
-
|
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
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
91
|
-
|
99
|
+
def reset_image_inspect(image_id)
|
100
|
+
image_inspects.delete(image_id)
|
92
101
|
end
|
93
102
|
|
94
|
-
def
|
95
|
-
@
|
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
|
data/lib/dapp/version.rb
CHANGED