dapp 0.24.12 → 0.25.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/bin/dapp +0 -4
- data/lib/dapp.rb +0 -4
- data/lib/dapp/cli.rb +2 -5
- data/lib/dapp/cli/command/base.rb +1 -7
- data/lib/dapp/dapp.rb +4 -22
- data/lib/dapp/dapp/option_tags.rb +0 -6
- data/lib/dapp/dimg/build/stage/base.rb +1 -3
- data/lib/dapp/dimg/build/stage/ga_base.rb +1 -1
- data/lib/dapp/dimg/build/stage/ga_latest_patch.rb +1 -3
- data/lib/dapp/dimg/cli/command/base.rb +4 -0
- data/lib/dapp/dimg/cli/command/dimg/build.rb +31 -2
- data/lib/dapp/dimg/config/directive/dimg/validation.rb +21 -7
- data/lib/dapp/dimg/config/directive/git_artifact_remote.rb +4 -3
- data/lib/dapp/dimg/dimg.rb +0 -2
- data/lib/dapp/dimg/dimg/path.rb +0 -4
- data/lib/dapp/dimg/docker_registry/base.rb +10 -0
- data/lib/dapp/dimg/git_artifact.rb +1 -1
- data/lib/dapp/dimg/git_repo/base.rb +18 -2
- data/lib/dapp/dimg/git_repo/local.rb +2 -2
- data/lib/dapp/helper/trivia.rb +2 -18
- data/lib/dapp/kube/dapp/command/deploy.rb +59 -5
- data/lib/dapp/kube/dapp/command/render.rb +2 -2
- data/lib/dapp/kube/helm/release.rb +26 -17
- data/lib/dapp/version.rb +2 -2
- metadata +2 -32
- data/lib/dapp/dapp/sentry.rb +0 -112
- data/lib/dapp/helper/url.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9feef0467f4a300a3890d8c35fca220590a9fd19
|
4
|
+
data.tar.gz: eb7cb2377a0dd260976a6bbfd08c51cf50e4c4bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0050bb050988788005d6af8dd2432ca5b3e9b02dd6f5fbd3203deab1adc36253f0d460ab31bac8c3ba17229a21c00ba1c6c180202496ff76a3e030cb665b360c
|
7
|
+
data.tar.gz: 19cc26da6da554416efa0969d0ccc88e061578cbd8b4147cf6af785eba4169555d7f10ec73fb85ee2a729c12d2795e793e1f6b86bb36d1900ec9154e7b94c23d
|
data/bin/dapp
CHANGED
data/lib/dapp.rb
CHANGED
@@ -26,8 +26,6 @@ require 'zlib'
|
|
26
26
|
require 'slugify'
|
27
27
|
require 'base64'
|
28
28
|
require 'io/console'
|
29
|
-
require 'sentry-raven'
|
30
|
-
require 'toml-rb'
|
31
29
|
|
32
30
|
require 'dapp/version'
|
33
31
|
require 'dapp/core_ext/hash'
|
@@ -38,7 +36,6 @@ require 'dapp/helper/sha256'
|
|
38
36
|
require 'dapp/helper/net_status'
|
39
37
|
require 'dapp/helper/tar'
|
40
38
|
require 'dapp/helper/yaml'
|
41
|
-
require 'dapp/helper/url'
|
42
39
|
require 'dapp/prctl'
|
43
40
|
require 'dapp/error/mod/user'
|
44
41
|
require 'dapp/error/base'
|
@@ -59,7 +56,6 @@ require 'dapp/config/directive/base'
|
|
59
56
|
require 'dapp/config/config'
|
60
57
|
require 'dapp/dapp/lock'
|
61
58
|
require 'dapp/dapp/ssh_agent'
|
62
|
-
require 'dapp/dapp/sentry'
|
63
59
|
require 'dapp/dapp/git_artifact'
|
64
60
|
require 'dapp/dapp/dappfile'
|
65
61
|
require 'dapp/dapp/chef'
|
data/lib/dapp/cli.rb
CHANGED
@@ -5,7 +5,7 @@ module Dapp
|
|
5
5
|
extend Helper::Cli
|
6
6
|
include Helper::Trivia
|
7
7
|
|
8
|
-
SUBCOMMANDS = ['dimg', 'kube', 'update', 'slug'].freeze
|
8
|
+
SUBCOMMANDS = ['dimg', 'deployment', 'kube', 'update', 'slug'].freeze
|
9
9
|
|
10
10
|
banner <<BANNER.freeze
|
11
11
|
Usage: dapp subcommand [subcommand options]
|
@@ -13,6 +13,7 @@ Usage: dapp subcommand [subcommand options]
|
|
13
13
|
Available subcommands: (for details, dapp SUB-COMMAND --help)
|
14
14
|
|
15
15
|
dapp dimg
|
16
|
+
dapp deployment
|
16
17
|
dapp kube
|
17
18
|
dapp update
|
18
19
|
dapp slug STRING
|
@@ -37,10 +38,6 @@ BANNER
|
|
37
38
|
show_options: true,
|
38
39
|
exit: 0
|
39
40
|
|
40
|
-
class << self
|
41
|
-
attr_accessor :dapp_object
|
42
|
-
end
|
43
|
-
|
44
41
|
def initialize(*args)
|
45
42
|
super(*args)
|
46
43
|
|
@@ -58,8 +58,6 @@ module Dapp
|
|
58
58
|
|
59
59
|
def run_dapp_command(run_method, options: {}, log_running_time: true, try_host_docker_login: false)
|
60
60
|
dapp = ::Dapp::Dapp.new(options: options)
|
61
|
-
::Dapp::CLI.dapp_object = dapp
|
62
|
-
dapp.sentry_message("Manual usage: `#{options[:dapp_command]}` command") unless ENV['CI']
|
63
61
|
|
64
62
|
log_dapp_running_time(dapp, ignore: !log_running_time) do
|
65
63
|
begin
|
@@ -76,10 +74,6 @@ module Dapp
|
|
76
74
|
end
|
77
75
|
end
|
78
76
|
|
79
|
-
def run_method
|
80
|
-
class_to_lowercase
|
81
|
-
end
|
82
|
-
|
83
77
|
def log_dapp_running_time(dapp, ignore: false)
|
84
78
|
return yield if ignore
|
85
79
|
|
@@ -101,7 +95,7 @@ module Dapp
|
|
101
95
|
self.class.print_error_with_help_and_die! self, "cannot use alias options --run-dir, --build-dir, --deploy-dir at the same time"
|
102
96
|
end
|
103
97
|
|
104
|
-
config.merge(build_dir: dirs.compact.first,
|
98
|
+
config.merge(build_dir: dirs.compact.first, **kwargs)
|
105
99
|
end
|
106
100
|
end
|
107
101
|
end
|
data/lib/dapp/dapp.rb
CHANGED
@@ -17,13 +17,10 @@ module Dapp
|
|
17
17
|
include Logging::Paint
|
18
18
|
|
19
19
|
include SshAgent
|
20
|
-
include Sentry
|
21
|
-
|
22
20
|
include Helper::Sha256
|
23
|
-
extend
|
21
|
+
extend Helper::Trivia
|
24
22
|
include Helper::Trivia
|
25
23
|
include Helper::Tar
|
26
|
-
include Helper::Url
|
27
24
|
|
28
25
|
include Deps::Toolchain
|
29
26
|
include Deps::Gitartifact
|
@@ -46,18 +43,6 @@ module Dapp
|
|
46
43
|
self.class.options
|
47
44
|
end
|
48
45
|
|
49
|
-
def settings
|
50
|
-
@settings ||= begin
|
51
|
-
settings_path = File.join(self.class.home_dir, "settings.toml")
|
52
|
-
|
53
|
-
if File.exists? settings_path
|
54
|
-
TomlRB.load_file(settings_path)
|
55
|
-
else
|
56
|
-
{}
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
46
|
def name
|
62
47
|
@name ||= begin
|
63
48
|
n = begin
|
@@ -107,8 +92,8 @@ module Dapp
|
|
107
92
|
self.class.tmp_base_dir
|
108
93
|
end
|
109
94
|
|
110
|
-
def
|
111
|
-
@
|
95
|
+
def build_path(*path)
|
96
|
+
@build_path ||= begin
|
112
97
|
if option_build_dir
|
113
98
|
Pathname.new(option_build_dir)
|
114
99
|
else
|
@@ -116,10 +101,7 @@ module Dapp
|
|
116
101
|
Pathname.new(dir)
|
117
102
|
end.expand_path.tap(&:mkpath)
|
118
103
|
end
|
119
|
-
|
120
|
-
|
121
|
-
def build_path(*path)
|
122
|
-
make_path(build_dir, *path)
|
104
|
+
make_path(@build_path, *path)
|
123
105
|
end
|
124
106
|
|
125
107
|
def local_git_artifact_exclude_paths(&blk)
|
@@ -7,12 +7,6 @@ module Dapp
|
|
7
7
|
|
8
8
|
def tags_by_scheme
|
9
9
|
@tags_by_scheme_name ||= begin
|
10
|
-
if simple_tags[:custom].any?
|
11
|
-
if settings.fetch("sentry", {}).fetch("detect-push-tag-usage", false)
|
12
|
-
sentry_message("--tag or --tag-slug usage detected", extra: {"slug_tags" => simple_tags})
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
10
|
[simple_tags, branch_tags, commit_tags, build_tags, ci_tags].reduce({}) do |some_tags_by_scheme, tags_by_scheme|
|
17
11
|
tags_by_scheme.in_depth_merge(some_tags_by_scheme)
|
18
12
|
end.tap do |tags_by_scheme|
|
@@ -189,10 +189,8 @@ module Dapp
|
|
189
189
|
commits[git_artifact] ||= begin
|
190
190
|
if image.built?
|
191
191
|
image.labels[dimg.dapp.dimgstage_g_a_commit_label(git_artifact.paramshash)]
|
192
|
-
|
192
|
+
else
|
193
193
|
git_artifact.latest_commit
|
194
|
-
elsif prev_stage
|
195
|
-
prev_stage.layer_commit(git_artifact)
|
196
194
|
end
|
197
195
|
end
|
198
196
|
end
|
@@ -10,7 +10,7 @@ module Dapp
|
|
10
10
|
image.add_volume "#{dimg.tmp_path('patches')}:#{dimg.container_tmp_path('patches')}:ro"
|
11
11
|
|
12
12
|
dimg.git_artifacts.each do |git_artifact|
|
13
|
-
image.add_service_change_label(dimg.dapp.dimgstage_g_a_commit_label(git_artifact.paramshash).to_sym =>
|
13
|
+
image.add_service_change_label(dimg.dapp.dimgstage_g_a_commit_label(git_artifact.paramshash).to_sym => git_artifact.latest_commit)
|
14
14
|
image.add_command git_artifact.send(apply_command_method, self)
|
15
15
|
end
|
16
16
|
end
|
@@ -28,9 +28,7 @@ module Dapp
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def commit_list
|
31
|
-
dimg.git_artifacts
|
32
|
-
.select { |ga| ga.repo.commit_exists?(prev_stage.layer_commit(ga)) && ga.patch_any_changes?(self) }
|
33
|
-
.map(&method(:layer_commit))
|
31
|
+
dimg.git_artifacts.map { |git_artifact| layer_commit(git_artifact) }
|
34
32
|
end
|
35
33
|
|
36
34
|
def git_artifacts_dev_patch_hashes
|
@@ -22,6 +22,18 @@ BANNER
|
|
22
22
|
:g_a_pre_setup_patch, :setup, :after_setup_artifact, :g_a_artifact_patch, :build_artifact
|
23
23
|
]
|
24
24
|
|
25
|
+
introspect_stage_proc = proc do |stages|
|
26
|
+
proc { |val| val.to_sym.tap { |v| in_validate!(v, stages) } }
|
27
|
+
end
|
28
|
+
|
29
|
+
introspect_before_proc = proc do |stages|
|
30
|
+
proc do |val|
|
31
|
+
val_sym = val.to_sym
|
32
|
+
introspect_stage_proc.call(stages[1..-1]).call(val_sym)
|
33
|
+
stages[stages.index(val_sym) - 1]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
25
37
|
option :tmp_dir_prefix,
|
26
38
|
long: '--tmp-dir-prefix PREFIX',
|
27
39
|
description: 'Tmp directory prefix (/tmp by default). Used for build process service directories.'
|
@@ -48,12 +60,22 @@ BANNER
|
|
48
60
|
option :introspect_stage,
|
49
61
|
long: '--introspect-stage STAGE',
|
50
62
|
description: "Introspect one of the following stages (#{list_msg_format(introspected_stages)})",
|
51
|
-
proc:
|
63
|
+
proc: introspect_stage_proc.call(introspected_stages)
|
64
|
+
|
65
|
+
option :introspect_before,
|
66
|
+
long: '--introspect-before STAGE',
|
67
|
+
description: "Introspect stage before one of the following stages (#{list_msg_format(introspected_stages[1..-1])})",
|
68
|
+
proc: introspect_before_proc.call(introspected_stages)
|
52
69
|
|
53
70
|
option :introspect_artifact_stage,
|
54
71
|
long: '--introspect-artifact-stage STAGE',
|
55
72
|
description: "Introspect one of the following stages (#{list_msg_format(artifact_introspected_stages)})",
|
56
|
-
proc:
|
73
|
+
proc: introspect_stage_proc.call(artifact_introspected_stages)
|
74
|
+
|
75
|
+
option :introspect_artifact_before,
|
76
|
+
long: '--introspect-artifact-before STAGE',
|
77
|
+
description: "Introspect stage before one of the following stages (#{list_msg_format(artifact_introspected_stages[1..-1])})",
|
78
|
+
proc: introspect_before_proc.call(artifact_introspected_stages)
|
57
79
|
|
58
80
|
option :ssh_key,
|
59
81
|
long: '--ssh-key SSH_KEY',
|
@@ -75,6 +97,13 @@ BANNER
|
|
75
97
|
long: '--force-save-cache',
|
76
98
|
boolean: true,
|
77
99
|
default: false
|
100
|
+
|
101
|
+
def cli_options(**kwargs)
|
102
|
+
super.tap do |config|
|
103
|
+
config[:introspect_stage] ||= config[:introspect_before]
|
104
|
+
config[:introspect_artifact_stage] ||= config[:introspect_artifact_before]
|
105
|
+
end
|
106
|
+
end
|
78
107
|
end
|
79
108
|
end
|
80
109
|
end
|
@@ -4,8 +4,6 @@ module Dapp
|
|
4
4
|
module Directive
|
5
5
|
class Dimg < Base
|
6
6
|
module Validation
|
7
|
-
include Helper::Trivia
|
8
|
-
|
9
7
|
def validate!
|
10
8
|
directives_validate!
|
11
9
|
validate_scratch!
|
@@ -140,13 +138,29 @@ module Dapp
|
|
140
138
|
end
|
141
139
|
|
142
140
|
def validate_artifact!(verifiable_artifact, artifact)
|
143
|
-
|
144
|
-
|
145
|
-
!
|
141
|
+
verifiable_artifact[:include_paths].each do |verifiable_path|
|
142
|
+
potential_conflicts = artifact[:include_paths].select { |path| path.start_with?(verifiable_path) }
|
143
|
+
validate_artifact_path!(verifiable_artifact, potential_conflicts)
|
144
|
+
end
|
145
|
+
|
146
|
+
if verifiable_artifact[:include_paths].empty?
|
147
|
+
if artifact[:include_paths].empty? || verifiable_artifact[:exclude_paths].empty?
|
148
|
+
raise ::Dapp::Error::Config, code: :artifact_conflict
|
149
|
+
else
|
150
|
+
validate_artifact_path!(verifiable_artifact, artifact[:include_paths])
|
151
|
+
end
|
146
152
|
end
|
147
|
-
|
153
|
+
end
|
148
154
|
|
149
|
-
|
155
|
+
def validate_artifact_path!(verifiable_artifact, potential_conflicts)
|
156
|
+
raise ::Dapp::Error::Config, code: :artifact_conflict unless begin
|
157
|
+
potential_conflicts.all? do |path|
|
158
|
+
loop do
|
159
|
+
break if verifiable_artifact[:exclude_paths].include?(path) || ((path = File.dirname(path)) == '.')
|
160
|
+
end
|
161
|
+
verifiable_artifact[:exclude_paths].include?(path)
|
162
|
+
end
|
163
|
+
end
|
150
164
|
end
|
151
165
|
|
152
166
|
def _associated_artifacts
|
@@ -3,13 +3,14 @@ module Dapp
|
|
3
3
|
module Config
|
4
4
|
module Directive
|
5
5
|
class GitArtifactRemote < GitArtifactLocal
|
6
|
-
include ::Dapp::Helper::Url
|
7
|
-
|
8
6
|
attr_reader :_url, :_name, :_branch, :_commit
|
9
7
|
|
10
8
|
def initialize(url, **kwargs, &blk)
|
11
9
|
@_url = url
|
12
|
-
|
10
|
+
|
11
|
+
url_without_scheme = url.split("://", 2).last
|
12
|
+
url_without_creds = url_without_scheme.split(":", 2).last
|
13
|
+
@_name = url_without_creds.gsub(%r{.*?([^\/ ]+\/[^\/ ]+)\.git}, '\\1')
|
13
14
|
|
14
15
|
super(**kwargs, &blk)
|
15
16
|
end
|
data/lib/dapp/dimg/dimg.rb
CHANGED
@@ -189,8 +189,6 @@ module Dapp
|
|
189
189
|
end
|
190
190
|
|
191
191
|
def cleanup_tmp
|
192
|
-
return unless tmp_dir_exists?
|
193
|
-
|
194
192
|
# В tmp-директории могли остаться файлы, владельцами которых мы не являемся.
|
195
193
|
# Такие файлы могут попасть туда при экспорте файлов артефакта.
|
196
194
|
# Чтобы от них избавиться — запускаем docker-контейнер под root-пользователем
|
data/lib/dapp/dimg/dimg/path.rb
CHANGED
@@ -35,6 +35,7 @@ module Dapp
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def image_delete(tag)
|
38
|
+
image_blobs(tag).each { |hash| blob_delete(hash.values.first) }
|
38
39
|
api_request(repo_suffix, "/manifests/#{image_digest(tag)}",
|
39
40
|
method: :delete,
|
40
41
|
expects: [202, 404],
|
@@ -53,6 +54,10 @@ module Dapp
|
|
53
54
|
headers: { Accept: 'application/vnd.docker.distribution.manifest.v2+json' }).headers['Docker-Content-Digest']
|
54
55
|
end
|
55
56
|
|
57
|
+
def image_blobs(tag)
|
58
|
+
manifest_v1(tag)['fsLayers']
|
59
|
+
end
|
60
|
+
|
56
61
|
def manifest_v1(tag)
|
57
62
|
api_request(repo_suffix, "/manifests/#{tag}")
|
58
63
|
end
|
@@ -62,6 +67,11 @@ module Dapp
|
|
62
67
|
headers: { Accept: 'application/vnd.docker.distribution.manifest.v2+json' })
|
63
68
|
end
|
64
69
|
|
70
|
+
def blob_delete(id)
|
71
|
+
api_request(repo_suffix, "/blobs/#{id}",
|
72
|
+
method: :delete, expects: [202, 404])
|
73
|
+
end
|
74
|
+
|
65
75
|
def api_request(*uri, **options)
|
66
76
|
JSON.load(raw_api_request(*uri, **options).body)
|
67
77
|
end
|
@@ -121,7 +121,7 @@ module Dapp
|
|
121
121
|
last_part_path = path_parts.shift
|
122
122
|
test_path = [test_path, last_part_path].compact.join('/')
|
123
123
|
|
124
|
-
non_match = !File.fnmatch(test_path, embedded_rel_path, File::FNM_PATHNAME
|
124
|
+
non_match = !File.fnmatch(test_path, embedded_rel_path, File::FNM_PATHNAME)
|
125
125
|
part_for_all = (last_part_path == '**')
|
126
126
|
|
127
127
|
if non_match || part_for_all
|
@@ -104,12 +104,12 @@ module Dapp
|
|
104
104
|
|
105
105
|
def patches(from, to, paths: [], exclude_paths: [], **kwargs)
|
106
106
|
diff(from, to, **kwargs).patches.select do |patch|
|
107
|
-
|
107
|
+
ignore_patch?(patch, paths: paths, exclude_paths: exclude_paths)
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
111
|
def ignore_patch?(patch, paths: [], exclude_paths: [])
|
112
|
-
ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
|
112
|
+
!ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
|
113
113
|
end
|
114
114
|
|
115
115
|
def entries(commit, paths: [], exclude_paths: [])
|
@@ -227,6 +227,22 @@ module Dapp
|
|
227
227
|
paths.empty? || paths.any? { |p| check_path?(path, p) || check_subpath?(path, p) }
|
228
228
|
end
|
229
229
|
end
|
230
|
+
|
231
|
+
def ignore_path?(path, paths: [], exclude_paths: [])
|
232
|
+
ignore_path_base(path, exclude_paths: exclude_paths) do
|
233
|
+
paths.empty? ||
|
234
|
+
paths.any? do |p|
|
235
|
+
File.fnmatch?(p, path, File::FNM_PATHNAME) ||
|
236
|
+
File.fnmatch?(File.join(p, '**', '*'), path, File::FNM_PATHNAME)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def ignore_path_base(path, exclude_paths: [])
|
242
|
+
is_exclude_path = exclude_paths.any? { |p| check_path?(path, p) }
|
243
|
+
is_include_path = yield
|
244
|
+
is_exclude_path || !is_include_path
|
245
|
+
end
|
230
246
|
end
|
231
247
|
end
|
232
248
|
end
|
@@ -48,9 +48,9 @@ module Dapp
|
|
48
48
|
delta_new_file = patch.delta.new_file
|
49
49
|
args = [delta_new_file[:path], paths: paths, exclude_paths: exclude_paths]
|
50
50
|
if nested_git_repository_mode?(delta_new_file[:mode])
|
51
|
-
ignore_directory?(*args)
|
51
|
+
!ignore_directory?(*args)
|
52
52
|
else
|
53
|
-
ignore_path?(*args)
|
53
|
+
!ignore_path?(*args)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
data/lib/dapp/helper/trivia.rb
CHANGED
@@ -28,28 +28,12 @@ module Dapp
|
|
28
28
|
Pathname.new(File.join(base.to_s, *path.compact.map(&:to_s)))
|
29
29
|
end
|
30
30
|
|
31
|
-
def ignore_path?(path, paths: [], exclude_paths: [])
|
32
|
-
ignore_path_base(path, exclude_paths: exclude_paths) do
|
33
|
-
paths.empty? ||
|
34
|
-
paths.any? do |p|
|
35
|
-
File.fnmatch?(p, path, File::FNM_PATHNAME|File::FNM_DOTMATCH) ||
|
36
|
-
File.fnmatch?(File.join(p, '**', '*'), path, File::FNM_PATHNAME|File::FNM_DOTMATCH)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def ignore_path_base(path, exclude_paths: [])
|
42
|
-
is_exclude_path = exclude_paths.any? { |p| check_path?(path, p) }
|
43
|
-
is_include_path = yield
|
44
|
-
is_exclude_path || !is_include_path
|
45
|
-
end
|
46
|
-
|
47
31
|
def check_path?(path, format)
|
48
|
-
path_checker(path) { |checking_path| File.fnmatch(format, checking_path, File::FNM_PATHNAME
|
32
|
+
path_checker(path) { |checking_path| File.fnmatch(format, checking_path, File::FNM_PATHNAME) }
|
49
33
|
end
|
50
34
|
|
51
35
|
def check_subpath?(path, format)
|
52
|
-
path_checker(format) { |checking_path| File.fnmatch(checking_path, path, File::FNM_PATHNAME
|
36
|
+
path_checker(format) { |checking_path| File.fnmatch(checking_path, path, File::FNM_PATHNAME) }
|
53
37
|
end
|
54
38
|
|
55
39
|
def path_checker(path)
|
@@ -62,11 +62,53 @@ module Dapp
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
def kube_helm_auto_purge_trigger_file_path(release_name)
|
66
|
+
File.join(self.class.home_dir, "helm", release_name, "auto_purge_failed_release_on_next_deploy")
|
67
|
+
end
|
68
|
+
|
69
|
+
def kube_create_helm_auto_purge_trigger_file(release_name)
|
70
|
+
FileUtils.mkdir_p File.dirname(kube_helm_auto_purge_trigger_file_path(release_name))
|
71
|
+
FileUtils.touch kube_helm_auto_purge_trigger_file_path(release_name)
|
72
|
+
end
|
73
|
+
|
74
|
+
def kube_delete_helm_auto_purge_trigger_file(release_name)
|
75
|
+
if File.exists? kube_helm_auto_purge_trigger_file_path(release_name)
|
76
|
+
FileUtils.rm_rf kube_helm_auto_purge_trigger_file_path(release_name)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
65
80
|
def kube_run_deploy(release)
|
66
81
|
log_process("Deploy release #{release.name}") do
|
67
|
-
|
82
|
+
helm_status_res = shellout("helm status #{release.name} --output json")
|
83
|
+
helm_status = {}
|
84
|
+
helm_status = JSON.load(helm_status_res.stdout) if helm_status_res.status.success?
|
85
|
+
release_exists = nil
|
86
|
+
|
87
|
+
if not helm_status_res.status.success?
|
88
|
+
# Helm release is not exists.
|
89
|
+
release_exists = false
|
90
|
+
|
91
|
+
# Create purge-trigger for the next run.
|
92
|
+
kube_create_helm_auto_purge_trigger_file(release.name)
|
93
|
+
elsif helm_status.fetch("info", {}).fetch("status", {}).fetch("code", nil) == 4
|
94
|
+
# Helm release is in FAILED state
|
95
|
+
release_exists = true
|
96
|
+
|
97
|
+
if File.exists? kube_helm_auto_purge_trigger_file_path(release.name)
|
98
|
+
log_process("Purge helm release #{release.name}") do
|
99
|
+
shellout!("helm delete --purge #{release.name}")
|
100
|
+
end
|
101
|
+
|
102
|
+
# Purge-trigger file remains to exist
|
103
|
+
release_exists = false
|
104
|
+
end
|
105
|
+
else
|
106
|
+
# Helm release is not in FAILED state
|
107
|
+
release_exists = true
|
108
|
+
kube_delete_helm_auto_purge_trigger_file(release.name)
|
109
|
+
end
|
68
110
|
|
69
|
-
|
111
|
+
kube_flush_hooks_jobs(release)
|
70
112
|
|
71
113
|
watch_hooks_by_type = release.jobs.values
|
72
114
|
.reduce({}) do |res, job|
|
@@ -116,7 +158,6 @@ module Dapp
|
|
116
158
|
# Поэтому перехватываем и просто отображаем произошедшую
|
117
159
|
# ошибку для информации пользователю без завершения работы dapp.
|
118
160
|
$stderr.puts(::Dapp::Dapp.paint_string(::Dapp::Helper::NetStatus.message(e), :warning))
|
119
|
-
sentry_exception(e, extra: {"job-spec" => job.spec})
|
120
161
|
end
|
121
162
|
|
122
163
|
end # Thread
|
@@ -127,18 +168,31 @@ module Dapp
|
|
127
168
|
|
128
169
|
deployment_managers.each(&:before_deploy)
|
129
170
|
|
130
|
-
log_process("
|
171
|
+
log_process("#{release_exists ? "Upgrade" : "Install"} helm release #{release.name}") do
|
131
172
|
watch_hooks_condition_mutex.synchronize do
|
132
173
|
deploy_has_began = true
|
133
174
|
# Фактически гарантируется лишь вывод сообщения log_process перед выводом из потока watch_thr
|
134
175
|
watch_hooks_condition.signal
|
135
176
|
end
|
136
177
|
|
137
|
-
cmd_res =
|
178
|
+
cmd_res = if release_exists
|
179
|
+
release.upgrade_helm_release
|
180
|
+
else
|
181
|
+
release.install_helm_release
|
182
|
+
end
|
138
183
|
|
139
184
|
if cmd_res.error?
|
185
|
+
if cmd_res.stderr.end_with? "has no deployed releases\n"
|
186
|
+
log_warning "[WARN] Helm release #{release.name} is in improper state: FAILED state and there was no successful releases yet"
|
187
|
+
log_warning "[WARN] Helm release #{release.name} will be removed with `helm delete --purge` on the next run of `dapp kube deploy`"
|
188
|
+
|
189
|
+
kube_create_helm_auto_purge_trigger_file(release.name)
|
190
|
+
end
|
191
|
+
|
140
192
|
raise ::Dapp::Error::Command, code: :kube_helm_failed, data: {output: (cmd_res.stdout + cmd_res.stderr).strip}
|
141
193
|
else
|
194
|
+
kube_delete_helm_auto_purge_trigger_file(release.name)
|
195
|
+
|
142
196
|
watch_hooks_thr.join if !dry_run? && watch_hooks_thr && watch_hooks_thr.alive?
|
143
197
|
log_info((cmd_res.stdout + cmd_res.stderr).strip)
|
144
198
|
end
|
@@ -13,8 +13,8 @@ module Dapp
|
|
13
13
|
template_relative_path_pattern = Pathname(File.expand_path(template_path_pattern)).subpath_of(path('.helm'))
|
14
14
|
template_relative_path_pattern ||= template_path_pattern
|
15
15
|
|
16
|
-
File.fnmatch?(template_relative_path_pattern, template_path_without_chart_name, File::FNM_PATHNAME
|
17
|
-
File.fnmatch?(template_relative_path_pattern, template_path, File::FNM_PATHNAME
|
16
|
+
File.fnmatch?(template_relative_path_pattern, template_path_without_chart_name, File::FNM_PATHNAME) ||
|
17
|
+
File.fnmatch?(template_relative_path_pattern, template_path, File::FNM_PATHNAME)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
else
|
@@ -49,15 +49,29 @@ module Dapp
|
|
49
49
|
end.to_h
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
def install_helm_release
|
53
|
+
unless dapp.dry_run?
|
54
|
+
dapp.kubernetes.create_namespace!(namespace) unless dapp.kubernetes.namespace?(namespace)
|
55
|
+
end
|
56
|
+
|
57
|
+
cmd = dapp.shellout([
|
58
|
+
"helm install #{chart_path}",
|
59
|
+
"--name #{name}",
|
60
|
+
*helm_additional_values_options,
|
61
|
+
*helm_set_options,
|
62
|
+
*helm_common_options,
|
63
|
+
].join(" "))
|
57
64
|
|
58
|
-
|
65
|
+
return cmd
|
66
|
+
end
|
59
67
|
|
60
|
-
|
68
|
+
def upgrade_helm_release
|
69
|
+
cmd = dapp.shellout([
|
70
|
+
"helm upgrade #{name} #{chart_path}",
|
71
|
+
*helm_additional_values_options,
|
72
|
+
*helm_set_options,
|
73
|
+
*helm_common_options
|
74
|
+
].join(" "))
|
61
75
|
|
62
76
|
return cmd
|
63
77
|
end
|
@@ -93,8 +107,8 @@ module Dapp
|
|
93
107
|
"helm",
|
94
108
|
"template",
|
95
109
|
chart_path,
|
96
|
-
|
97
|
-
|
110
|
+
helm_additional_values_options,
|
111
|
+
helm_set_options(without_registry: true),
|
98
112
|
("--namespace #{namespace}" if namespace),
|
99
113
|
].compact.join(" ")
|
100
114
|
|
@@ -113,7 +127,7 @@ module Dapp
|
|
113
127
|
end
|
114
128
|
end
|
115
129
|
|
116
|
-
def
|
130
|
+
def helm_additional_values_options
|
117
131
|
[].tap do |options|
|
118
132
|
options.concat(values.map { |p| "--values #{p}" })
|
119
133
|
end
|
@@ -123,7 +137,7 @@ module Dapp
|
|
123
137
|
@dimg_registry ||= dapp.dimg_registry(repo)
|
124
138
|
end
|
125
139
|
|
126
|
-
def
|
140
|
+
def helm_set_options(without_registry: false)
|
127
141
|
[].tap do |options|
|
128
142
|
options.concat set.map {|opt| "--set #{opt}"}
|
129
143
|
|
@@ -132,21 +146,16 @@ module Dapp
|
|
132
146
|
end
|
133
147
|
end
|
134
148
|
|
135
|
-
def
|
149
|
+
def helm_common_options(dry_run: nil)
|
136
150
|
dry_run = dapp.dry_run? if dry_run.nil?
|
137
151
|
|
138
152
|
[].tap do |options|
|
139
153
|
options << "--namespace #{namespace}" if namespace
|
140
|
-
options << '--install'
|
141
154
|
options << '--dry-run' if dry_run
|
142
155
|
options << '--debug' if dry_run
|
143
156
|
options << "--timeout #{deploy_timeout}" if deploy_timeout
|
144
157
|
end
|
145
158
|
end
|
146
|
-
|
147
|
-
class << self
|
148
|
-
|
149
|
-
end # << self
|
150
159
|
end # Helm::Release
|
151
160
|
end # Kube
|
152
161
|
end # Dapp
|
data/lib/dapp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dapp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Stolyarov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-shellout
|
@@ -186,34 +186,6 @@ dependencies:
|
|
186
186
|
- - ">="
|
187
187
|
- !ruby/object:Gem::Version
|
188
188
|
version: 1.0.6
|
189
|
-
- !ruby/object:Gem::Dependency
|
190
|
-
name: sentry-raven
|
191
|
-
requirement: !ruby/object:Gem::Requirement
|
192
|
-
requirements:
|
193
|
-
- - "~>"
|
194
|
-
- !ruby/object:Gem::Version
|
195
|
-
version: 2.7.2
|
196
|
-
type: :runtime
|
197
|
-
prerelease: false
|
198
|
-
version_requirements: !ruby/object:Gem::Requirement
|
199
|
-
requirements:
|
200
|
-
- - "~>"
|
201
|
-
- !ruby/object:Gem::Version
|
202
|
-
version: 2.7.2
|
203
|
-
- !ruby/object:Gem::Dependency
|
204
|
-
name: toml-rb
|
205
|
-
requirement: !ruby/object:Gem::Requirement
|
206
|
-
requirements:
|
207
|
-
- - "~>"
|
208
|
-
- !ruby/object:Gem::Version
|
209
|
-
version: 1.1.1
|
210
|
-
type: :runtime
|
211
|
-
prerelease: false
|
212
|
-
version_requirements: !ruby/object:Gem::Requirement
|
213
|
-
requirements:
|
214
|
-
- - "~>"
|
215
|
-
- !ruby/object:Gem::Version
|
216
|
-
version: 1.1.1
|
217
189
|
- !ruby/object:Gem::Dependency
|
218
190
|
name: bundler
|
219
191
|
requirement: !ruby/object:Gem::Requirement
|
@@ -476,7 +448,6 @@ files:
|
|
476
448
|
- lib/dapp/dapp/logging/paint.rb
|
477
449
|
- lib/dapp/dapp/logging/process.rb
|
478
450
|
- lib/dapp/dapp/option_tags.rb
|
479
|
-
- lib/dapp/dapp/sentry.rb
|
480
451
|
- lib/dapp/dapp/shellout/base.rb
|
481
452
|
- lib/dapp/dapp/shellout/streaming.rb
|
482
453
|
- lib/dapp/dapp/slug.rb
|
@@ -678,7 +649,6 @@ files:
|
|
678
649
|
- lib/dapp/helper/sha256.rb
|
679
650
|
- lib/dapp/helper/tar.rb
|
680
651
|
- lib/dapp/helper/trivia.rb
|
681
|
-
- lib/dapp/helper/url.rb
|
682
652
|
- lib/dapp/helper/yaml.rb
|
683
653
|
- lib/dapp/kube.rb
|
684
654
|
- lib/dapp/kube/cli/cli.rb
|
data/lib/dapp/dapp/sentry.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
module Dapp
|
2
|
-
class Dapp
|
3
|
-
module Sentry
|
4
|
-
def sentry_message(msg, **kwargs)
|
5
|
-
return if not ensure_sentry_configured
|
6
|
-
kwargs[:level] ||= "info"
|
7
|
-
Raven.capture_message(msg, _make_sentry_params(**kwargs))
|
8
|
-
end
|
9
|
-
|
10
|
-
def sentry_exception(exception, **kwargs)
|
11
|
-
return if not ensure_sentry_configured
|
12
|
-
(kwargs[:tags] ||= {})['error-code'] = begin
|
13
|
-
net_status = exception.net_status
|
14
|
-
[net_status[:context], net_status[:code]].compact.join('_')
|
15
|
-
end
|
16
|
-
Raven.capture_exception(exception, _make_sentry_params(**kwargs))
|
17
|
-
end
|
18
|
-
|
19
|
-
def ensure_sentry_configured
|
20
|
-
return false unless sentry_settings = settings["sentry"]
|
21
|
-
|
22
|
-
unless @sentry_settings_configured
|
23
|
-
Raven.configure do |config|
|
24
|
-
logger = ::Logger.new(STDOUT)
|
25
|
-
logger.level = ::Logger::WARN
|
26
|
-
|
27
|
-
config.logger = logger
|
28
|
-
config.dsn = sentry_settings["dsn"]
|
29
|
-
end
|
30
|
-
|
31
|
-
@sentry_settings_configured = true
|
32
|
-
end
|
33
|
-
|
34
|
-
return true
|
35
|
-
end
|
36
|
-
|
37
|
-
def _make_sentry_params(level: nil, tags: {}, extra: {}, user: {})
|
38
|
-
{
|
39
|
-
level: level,
|
40
|
-
tags: _sentry_tags_context.merge(tags),
|
41
|
-
extra: _sentry_extra_context.merge(extra),
|
42
|
-
user: _sentry_user_context.merge(user),
|
43
|
-
}
|
44
|
-
end
|
45
|
-
|
46
|
-
def _sentry_extra_context
|
47
|
-
@_sentry_extra_context ||= {
|
48
|
-
"pwd" => Dir.pwd,
|
49
|
-
"dapp-dir" => self.work_dir,
|
50
|
-
"options" => self.options,
|
51
|
-
"env-options" => {
|
52
|
-
"DAPP_FORCE_SAVE_CACHE" => ENV["DAPP_FORCE_SAVE_CACHE"],
|
53
|
-
"DAPP_BIN_DAPPFILE_YML" => ENV["DAPP_BIN_DAPPFILE_YML"],
|
54
|
-
"ANSIBLE_ARGS" => ENV["ANSIBLE_ARGS"],
|
55
|
-
"DAPP_CHEF_DEBUG" => ENV["DAPP_CHEF_DEBUG"],
|
56
|
-
},
|
57
|
-
}.tap {|extra|
|
58
|
-
extra["ci-env"] = {"CI" => ENV["CI"]}
|
59
|
-
ENV.select {|k, v| k.start_with?("CI_")}.each do |k, v|
|
60
|
-
extra["ci-env"][k] = v
|
61
|
-
end
|
62
|
-
}
|
63
|
-
end
|
64
|
-
|
65
|
-
def _sentry_tags_context
|
66
|
-
name = options[:name] ||
|
67
|
-
@_sentry_tags_context ||= {
|
68
|
-
"dapp-short-version" => ::Dapp::VERSION.split(".")[0..1].join("."),
|
69
|
-
"dapp-version" => ::Dapp::VERSION,
|
70
|
-
"dapp-build-cache-version" => ::Dapp::BUILD_CACHE_VERSION,
|
71
|
-
"dapp-command" => self.options[:dapp_command],
|
72
|
-
}.tap {|tags|
|
73
|
-
git_config_path = File.join(Dir.pwd, ".git/config")
|
74
|
-
|
75
|
-
tags["dapp-name"] = options[:name]
|
76
|
-
|
77
|
-
if File.exists? git_config_path
|
78
|
-
cfg = IniFile.load(File.join(Dir.pwd, ".git/config"))
|
79
|
-
remote_origin_cfg = cfg['remote "origin"']
|
80
|
-
remote_origin_url = remote_origin_cfg["url"]
|
81
|
-
if remote_origin_url
|
82
|
-
tags["dapp-name"] ||= begin
|
83
|
-
repo_name = remote_origin_url.split('/').last
|
84
|
-
repo_name = repo_name[/.*(?=\.git)/] if repo_name.end_with? '.git'
|
85
|
-
repo_name
|
86
|
-
end
|
87
|
-
|
88
|
-
tags["git-host"] = self.get_host_from_git_url(remote_origin_url)
|
89
|
-
|
90
|
-
git_name = self.git_url_to_name(remote_origin_url)
|
91
|
-
|
92
|
-
tags["git-group"] = git_name.partition("/")[0]
|
93
|
-
tags["git-name"] = git_name
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
tags["dapp-name"] ||= File.basename(Dir.pwd)
|
98
|
-
|
99
|
-
begin
|
100
|
-
ver = self.class.host_docker_minor_version
|
101
|
-
tags["docker-minor-version"] = ver.to_s
|
102
|
-
rescue ::Exception
|
103
|
-
end
|
104
|
-
}
|
105
|
-
end
|
106
|
-
|
107
|
-
def _sentry_user_context
|
108
|
-
@_sentry_user_context ||= {}
|
109
|
-
end
|
110
|
-
end # Sentry
|
111
|
-
end # Dapp
|
112
|
-
end # Dapp
|
data/lib/dapp/helper/url.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Dapp
|
2
|
-
module Helper
|
3
|
-
module Url
|
4
|
-
def git_url_to_name(url)
|
5
|
-
url_without_scheme = url.split("://", 2).last
|
6
|
-
# This may be broken, because "@" should delimit creds, not a ":"
|
7
|
-
url_without_creds = url_without_scheme.split(":", 2).last
|
8
|
-
url_without_creds.gsub(%r{.*?([^\/ ]+\/[^\/ ]+)\.git}, '\\1')
|
9
|
-
end
|
10
|
-
|
11
|
-
def get_host_from_git_url(url)
|
12
|
-
url_without_scheme = url.split("://", 2).last
|
13
|
-
url_without_creds = url_without_scheme.split("@", 2).last
|
14
|
-
|
15
|
-
# Split out part after ":" in this kind of url: github.com:flant/dapp.git
|
16
|
-
url_part = url_without_creds.split(":", 2).first
|
17
|
-
|
18
|
-
# Split out part after first "/": github.com/flant/dapp.git
|
19
|
-
url_part.split("/", 2).first
|
20
|
-
end
|
21
|
-
end # Url
|
22
|
-
end # Helper
|
23
|
-
end # Dapp
|