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 +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