dapp 0.24.12 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cd3ff0c4bceec9cdd276f5fe5ad81ebf540ff88
4
- data.tar.gz: 0757dc0b74af4c3acebfe2143c236e1fb0470f2b
3
+ metadata.gz: 9feef0467f4a300a3890d8c35fca220590a9fd19
4
+ data.tar.gz: eb7cb2377a0dd260976a6bbfd08c51cf50e4c4bf
5
5
  SHA512:
6
- metadata.gz: d3cf61182dba6fdd9c610b5de68fa379c0c58dfc859936751c4744852fe7961ebff2a5d61c1ea9362fe244fd45de04e2e09becada2b5c64aa6efae9477c3681f
7
- data.tar.gz: f0e10a6ff4126492b75cc7806bc9cb5c4667cf47a6f7b608e4906ab4b92dd25e40fd6cda72449955c98e4ab289cec7455ecc79a31cc024b26686eb24ca34ddbd
6
+ metadata.gz: 0050bb050988788005d6af8dd2432ca5b3e9b02dd6f5fbd3203deab1adc36253f0d460ab31bac8c3ba17229a21c00ba1c6c180202496ff76a3e030cb665b360c
7
+ data.tar.gz: 19cc26da6da554416efa0969d0ccc88e061578cbd8b4147cf6af785eba4169555d7f10ec73fb85ee2a729c12d2795e793e1f6b86bb36d1900ec9154e7b94c23d
data/bin/dapp CHANGED
@@ -28,10 +28,6 @@ begin
28
28
  $stderr.puts "\033[1m\033[90mStacktrace dumped to #{filename}\033[0m"
29
29
  end
30
30
 
31
- if Dapp::CLI.dapp_object
32
- Dapp::CLI.dapp_object.sentry_exception(e)
33
- end
34
-
35
31
  raise
36
32
  end
37
33
  rescue Dapp::Error::Shellout => e
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, dapp_command: run_method, **kwargs)
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 Helper::Trivia
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 build_dir
111
- @build_dir ||= begin
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
- end
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
- elsif g_a_stage? && !empty?
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 => layer_commit(git_artifact))
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
@@ -9,6 +9,10 @@ module Dapp::Dimg::CLI
9
9
  self.class.parse_options(self, argv)
10
10
  run_dapp_command(run_method, options: cli_options(dimgs_patterns: cli_arguments))
11
11
  end
12
+
13
+ def run_method
14
+ class_to_lowercase
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -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: proc { |val| val.to_sym.tap { |v| in_validate!(v, introspected_stages) } }
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: proc { |val| val.to_sym.tap { |v| in_validate!(v, artifact_introspected_stages) } }
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
- cases = []
144
- cases << verifiable_artifact[:include_paths].any? do |verifiable_path|
145
- !ignore_path?(verifiable_path, paths: artifact[:include_paths], exclude_paths: artifact[:exclude_paths])
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
- cases << (verifiable_artifact[:include_paths].empty? && artifact[:include_paths].empty?)
153
+ end
148
154
 
149
- raise ::Dapp::Error::Config, code: :artifact_conflict if cases.any?
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
- @_name = git_url_to_name(url)
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
@@ -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-пользователем
@@ -6,10 +6,6 @@ module Dapp
6
6
  dapp.path(*path).expand_path
7
7
  end
8
8
 
9
- def tmp_dir_exists?
10
- @tmp_path != nil
11
- end
12
-
13
9
  def tmp_path(*path)
14
10
  @tmp_path ||= Dir.mktmpdir('dapp-', dapp.tmp_base_dir)
15
11
  make_path(@tmp_path, *path).expand_path.tap { |p| p.parent.mkpath }
@@ -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|File::FNM_DOTMATCH)
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
- !ignore_patch?(patch, paths: paths, exclude_paths: exclude_paths)
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
 
@@ -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|File::FNM_DOTMATCH) }
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|File::FNM_DOTMATCH) }
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
- kube_flush_hooks_jobs(release)
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
- release_exists = shellout("helm status #{release.name}").status.success?
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("Run helm") do
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 = release.helm_upgrade!
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|File::FNM_DOTMATCH) ||
17
- File.fnmatch?(template_relative_path_pattern, template_path, File::FNM_PATHNAME|File::FNM_DOTMATCH)
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 helm_upgrade!
53
- args = [
54
- name, chart_path, additional_values_options,
55
- set_options, upgrade_extra_options
56
- ].flatten
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
- dapp.kubernetes.create_namespace!(namespace) unless dapp.kubernetes.namespace?(namespace)
65
+ return cmd
66
+ end
59
67
 
60
- cmd = dapp.shellout "helm upgrade #{args.join(' ')}"
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
- additional_values_options,
97
- set_options(without_registry: true),
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 additional_values_options
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 set_options(without_registry: false)
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 upgrade_extra_options(dry_run: nil)
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
@@ -1,4 +1,4 @@
1
1
  module Dapp
2
- VERSION = "0.24.12"
3
- BUILD_CACHE_VERSION = 26.2
2
+ VERSION = "0.25.0"
3
+ BUILD_CACHE_VERSION = 26
4
4
  end
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.24.12
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-03-16 00:00:00.000000000 Z
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
@@ -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
@@ -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