dapp 0.24.3 → 0.24.4

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: 882b3acc8506bb005b8bf2a68aa9d1ac3e0cb432
4
- data.tar.gz: b40f3e4feda32bc080ed2ba8e6e5316a5dff9d6f
3
+ metadata.gz: c9a285aead0a2e57006e54a0839ab32cf4170529
4
+ data.tar.gz: cd58972b2de67689e2173bffe9524a0623e79bc1
5
5
  SHA512:
6
- metadata.gz: de722da958bc9b7610cd54f87d2c0b6362ed0828f7a086b9bb707f0f7d83b373e39eaa995dd6a603232c1c2aaf086f25b81cc881f18d8e6412a26a5334e8bf37
7
- data.tar.gz: 4ddc1ed3725f9c7434c3bd1fd6fd85a665dec825001188a2f8314919fa8a386af6934241de2d82abac07e9cb2ab7192ec052565b3dc9f6fab0aceccb4eecd08e
6
+ metadata.gz: 9dbb053e622ce8ac204b9529dbf2c1ca266b22a4f46fec3736963861b5e74148ff19f423e297c1a3a9d0fd44afeeb787c3a448978ab2d0219273a23448eca36f
7
+ data.tar.gz: f15547e0e17c93ba3e39ec915a1413b6445392212c9779333aa9d6742888b86d1291ee6d4be3f830dc79a21fe7af88001b32a428fbf64111da2d58eba3842772
@@ -44,6 +44,7 @@ en:
44
44
  expected_only_one_tag: 'Expected only one tag (`%{tags}`)!'
45
45
  kube_deploy_timeout: "Deploy timeout!"
46
46
  kube_connect_timeout: "Connect timeout when connecting to kube API."
47
+ kube_helm_failed: "Helm failed: %{output}"
47
48
  dapp:
48
49
  no_such_dimg: "No such dimg: `%{dimgs_patterns}`!"
49
50
  no_such_app: "No such app: `%{apps_patterns}`!"
@@ -80,7 +81,7 @@ en:
80
81
  stage_artifact_double_associate: "Can't use `%{stage}` stage for artifact; already used in `%{conflict_stage}` stage!"
81
82
  stage_artifact_not_supported_associated_stage: "Bad artifact stage `%{stage}`!"
82
83
  git_artifact_remote_branch_with_commit: "Remote git repo: use `commit` or `branch` directive!"
83
- artifact_conflict: "Conflict between artifacts paths!"
84
+ artifact_conflict: "Conflict between artifacts!\n\n%{dappfile_context}"
84
85
  scratch_unsupported_directive: "Scratch dimg has unsupported directive `%{directive}`!"
85
86
  scratch_artifact_required: "Scratch dimg without artifacts!"
86
87
  scratch_artifact_associated: "Scratch artifact can't be associated: not expected `before`/`after` attribute!"
@@ -115,7 +116,7 @@ en:
115
116
  rugged:
116
117
  git_repository_reference_error: "Git repo `%{name}`: %{message}!"
117
118
  rugged_remote_error: "Remote git repo `%{url}`: `%{message}`!"
118
- local_git_repository_does_not_exist: "Local git repo: doesn't exist!"
119
+ local_git_repository_does_not_exist: "Local git repo (`%{path}`): doesn't exist!"
119
120
  commit_not_found_in_local_git_repository: "Local git repo: commit `%{commit}` not found!\nIf commit has been rebased: run command `dapp dimg stages cleanup local --improper-git-commit`!"
120
121
  commit_not_found_in_remote_git_repository: "Remote git repo `%{url}`: commit `%{commit}` not found!\nIf commit has been rebased: run command `dapp dimg stages cleanup local --improper-git-commit`!"
121
122
  branch_not_exist_in_remote_git_repository: "Remote git repo `%{url}`: branch `%{branch}` not exist!"
@@ -136,6 +137,8 @@ en:
136
137
  server_connection_refused: "Kube server `%{url}` connection refused: %{error}"
137
138
  server_error: "Kube respond with server error code %{response_http_status}, request parameters: `%{request_parameters}`, response: `%{response_raw_body}`"
138
139
  container_stuck: "Pod's `%{pod_name}` container `%{container_name}` stuck in %{state} state: %{state_reason}: %{state_message}"
140
+ bad_image: "Pod `%{pod_name}` bad image: %{reason}: %{message}"
141
+ container_crash: "Pod's `%{pod_name}` container crashed: %{reason}: %{message}"
139
142
  secret:
140
143
  bad_data: "Data `%{data}` can't be decrypted: check encryption key and data!"
141
144
  key_length_too_short: "Encryption key isn't valid (required size %{required_size} bytes)!"
@@ -232,6 +232,7 @@ require 'dapp/dimg/dapp/command/build_context/export'
232
232
  require 'dapp/dimg/dapp/command/build_context/import'
233
233
  require 'dapp/dimg/dapp/command/build_context/common'
234
234
  require 'dapp/dimg/dapp/dappfile'
235
+ require 'dapp/dimg/dapp/dimg'
235
236
  require 'dapp/dimg/dapp/dapp'
236
237
  require 'dapp/dimg/docker_registry'
237
238
  require 'dapp/dimg/docker_registry/base/request'
@@ -254,6 +255,7 @@ require 'dapp/dimg/lock/base'
254
255
  require 'dapp/dimg/lock/file'
255
256
  require 'dapp/dimg/filelock'
256
257
  require 'dapp/dimg/git_repo/base'
258
+ require 'dapp/dimg/git_repo/local'
257
259
  require 'dapp/dimg/git_repo/own'
258
260
  require 'dapp/dimg/git_repo/remote'
259
261
  require 'dapp/dimg/git_artifact'
@@ -71,11 +71,14 @@ module Dapp
71
71
  end
72
72
 
73
73
  def git_own_repo_exist?
74
- git_own_repo.exist?
74
+ !git_own_repo.nil?
75
75
  end
76
76
 
77
77
  def git_own_repo
78
78
  @git_own_repo ||= Dimg::GitRepo::Own.new(self)
79
+ rescue Dimg::Error::Rugged => e
80
+ raise unless e.net_status[:code] == :local_git_repository_does_not_exist
81
+ nil
79
82
  end
80
83
 
81
84
  def path(*path)
@@ -22,9 +22,8 @@ module Dapp
22
22
  def artifacts
23
23
  @artifacts ||= begin
24
24
  dimg.config.public_send("_#{name}").map do |artifact|
25
- artifact_dimg = ::Dapp::Dimg::Artifact.new(config: artifact._config,
26
- dapp: dimg.dapp,
27
- ignore_git_fetch: dimg.ignore_git_fetch)
25
+ artifact_dimg = dimg.dapp.artifact_dimg(config: artifact._config,
26
+ ignore_git_fetch: dimg.ignore_git_fetch)
28
27
  { name: artifact._config._name, options: artifact._artifact_options, dimg: artifact_dimg }
29
28
  end
30
29
  end
@@ -5,13 +5,6 @@ module Dapp
5
5
  class ArtifactDimg < Dimg
6
6
  def validate_scratch!
7
7
  end
8
-
9
- def validate_artifacts_artifacts!
10
- end
11
-
12
- def validated_artifacts
13
- _git_artifact._local + _git_artifact._remote
14
- end
15
8
  end
16
9
  end
17
10
  end
@@ -136,6 +136,7 @@ module Dapp
136
136
 
137
137
  def artifacts_after_parsing!
138
138
  _artifacts_auto_excluding!
139
+ _artifact.map(&:_config).each(&:artifacts_after_parsing!)
139
140
  end
140
141
 
141
142
  protected
@@ -71,12 +71,39 @@ module Dapp
71
71
  verifiable_artifact = artifacts.shift
72
72
  artifacts.select { |a| a[:to] == verifiable_artifact[:to] }.each do |artifact|
73
73
  next if verifiable_artifact[:index] == artifact[:index]
74
- validate_artifact!(verifiable_artifact, artifact)
75
- validate_artifact!(artifact, verifiable_artifact)
74
+ begin
75
+ validate_artifact!(verifiable_artifact, artifact)
76
+ validate_artifact!(artifact, verifiable_artifact)
77
+ rescue ::Dapp::Error::Config => e
78
+ conflict_between_artifacts!(artifact, verifiable_artifact) if e.net_status[:code] == :artifact_conflict
79
+ raise
80
+ end
76
81
  end
77
82
  end
78
83
  end
79
84
 
85
+ def conflict_between_artifacts!(*formatted_artifacts)
86
+ artifacts = formatted_artifacts.flatten.map { |formatted_artifact| formatted_artifact[:related_artifact] }
87
+ dappfile_context = artifacts.map do |artifact|
88
+ artifact_directive = []
89
+ artifact_directive << begin
90
+ if artifact.is_a? Artifact::Export
91
+ "artifact.export('#{artifact._cwd}') do"
92
+ else
93
+ "git#{"('#{artifact._url}')" if artifact.respond_to?(:_url)}.add('#{artifact._cwd}') do"
94
+ end
95
+ end
96
+ [:include_paths, :exclude_paths].each do |directive|
97
+ next if (paths = artifact.send("_#{directive}")).empty?
98
+ artifact_directive << " #{directive} '#{paths.join("', '")}'"
99
+ end
100
+ artifact_directive << " to '#{artifact._to}'"
101
+ artifact_directive << 'end'
102
+ artifact_directive.join("\n")
103
+ end.join("\n\n")
104
+ raise ::Dapp::Error::Config, code: :artifact_conflict, data: { dappfile_context: dappfile_context }
105
+ end
106
+
80
107
  def validate_artifact_format(artifacts)
81
108
  artifacts.map do |a|
82
109
  path_format = proc { |path| File.expand_path(File.join('/', path, '/'))[1..-1] }
@@ -104,7 +131,8 @@ module Dapp
104
131
  index: artifacts.index(a),
105
132
  to: to,
106
133
  include_paths: include_paths,
107
- exclude_paths: exclude_paths
134
+ exclude_paths: exclude_paths,
135
+ related_artifact: a
108
136
  }
109
137
  end
110
138
  end
@@ -113,17 +141,26 @@ module Dapp
113
141
  verifiable_artifact[:include_paths].each do |verifiable_path|
114
142
  potential_conflicts = artifact[:include_paths].select { |path| path.start_with?(verifiable_path) }
115
143
  validate_artifact_path!(verifiable_artifact, potential_conflicts)
116
- end.empty? && verifiable_artifact[:exclude_paths].empty? && raise(::Dapp::Error::Config, code: :artifact_conflict)
117
- validate_artifact_path!(verifiable_artifact, artifact[:include_paths]) if verifiable_artifact[:include_paths].empty?
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
152
+ end
118
153
  end
119
154
 
120
155
  def validate_artifact_path!(verifiable_artifact, potential_conflicts)
121
- potential_conflicts.all? do |path|
122
- loop do
123
- break if verifiable_artifact[:exclude_paths].include?(path) || ((path = File.dirname(path)) == '.')
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)
124
162
  end
125
- verifiable_artifact[:exclude_paths].include?(path)
126
- end.tap { |res| res || raise(::Dapp::Error::Config, code: :artifact_conflict) }
163
+ end
127
164
  end
128
165
 
129
166
  def _associated_artifacts
@@ -8,7 +8,7 @@ module Dapp
8
8
 
9
9
  build_configs.each do |config|
10
10
  log_dimg_name_with_indent(config) do
11
- Dimg.new(config: config, dapp: self).build!
11
+ dimg(config: config).build!
12
12
  end
13
13
  end
14
14
  rescue ::Dapp::Error::Shellout, Error::Default
@@ -14,7 +14,7 @@ module Dapp
14
14
  def export_build_context_image_tar
15
15
  lock("#{name}.images", readonly: true) do
16
16
  context_images_names = build_configs.map do |config|
17
- Dimg.new(config: config, dapp: self, ignore_git_fetch: true).tagged_images.map(&:name)
17
+ dimg(config: config, ignore_git_fetch: true).tagged_images.map(&:name)
18
18
  end.flatten
19
19
 
20
20
  log_secondary_process(:images, short: true) do
@@ -123,9 +123,7 @@ module Dapp
123
123
  validate_repo_name!(repo)
124
124
  build_configs.each do |config|
125
125
  log_dimg_name_with_indent(config) do
126
- Dimg.new(config: config, dapp: self, ignore_git_fetch: true, should_be_built: should_be_built).tap do |dimg|
127
- yield dimg
128
- end
126
+ yield dimg(config: config, ignore_git_fetch: true, should_be_built: should_be_built)
129
127
  end
130
128
  end
131
129
  end
@@ -6,7 +6,7 @@ module Dapp
6
6
  def run(docker_options, command)
7
7
  one_dimg!
8
8
  setup_ssh_agent
9
- Dimg.new(config: build_configs.first, dapp: self, ignore_git_fetch: true, should_be_built: true).run(docker_options, command)
9
+ dimg(config: build_configs.first, ignore_git_fetch: true, should_be_built: true).run(docker_options, command)
10
10
  end
11
11
  end
12
12
  end
@@ -5,7 +5,7 @@ module Dapp
5
5
  module StageImage
6
6
  def stage_image
7
7
  one_dimg!
8
- puts Dimg.new(config: build_configs.first, dapp: self, ignore_git_fetch: true).stage_image_name(options[:stage])
8
+ puts dimg(config: build_configs.first, ignore_git_fetch: true).stage_image_name(options[:stage])
9
9
  end
10
10
  end
11
11
  end
@@ -56,7 +56,7 @@ module Dapp
56
56
  def dapp_git_repositories
57
57
  @dapp_git_repositories ||= begin
58
58
  {}.tap do |repositories|
59
- dimgs = build_configs.map { |config| Dimg.new(config: config, dapp: self, ignore_git_fetch: true) }
59
+ dimgs = build_configs.map { |config| dimg(config: config, ignore_git_fetch: true) }
60
60
  dimgs.each do |dimg|
61
61
  [dimg, dimg.artifacts]
62
62
  .flatten
@@ -3,6 +3,7 @@ module Dapp
3
3
  module Dapp
4
4
  module Dapp
5
5
  include Dappfile
6
+ include Dimg
6
7
 
7
8
  include Command::Common
8
9
  include Command::Run
@@ -0,0 +1,15 @@
1
+ module Dapp
2
+ module Dimg
3
+ module Dapp
4
+ module Dimg
5
+ def dimg(config:, **kwargs)
6
+ (@dimgs ||= {})[config._name] ||= ::Dapp::Dimg::Dimg.new(config: config, dapp: self, **kwargs)
7
+ end
8
+
9
+ def artifact_dimg(config:, **kwargs)
10
+ (@artifacts_dimgs ||= {})[config._name] ||= ::Dapp::Dimg::Artifact.new(config: config, dapp: self, **kwargs)
11
+ end
12
+ end # Dimg
13
+ end # Dapp
14
+ end # Dimg
15
+ end # Dapp
@@ -8,8 +8,9 @@ module Dapp
8
8
 
9
9
  def local_git_artifacts
10
10
  @local_git_artifact_list ||= [].tap do |artifacts|
11
+ break artifacts if (local_git_artifacts = Array(config._git_artifact._local)).empty?
11
12
  repo = GitRepo::Own.new(self)
12
- Array(config._git_artifact._local).map do |ga_config|
13
+ local_git_artifacts.map do |ga_config|
13
14
  artifacts.concat(generate_git_artifacts(repo, **ga_config._artifact_options))
14
15
  end
15
16
  end
@@ -27,14 +28,14 @@ module Dapp
27
28
  def generate_git_artifacts(repo, **git_artifact_options)
28
29
  [].tap do |artifacts|
29
30
  artifacts << (artifact = ::Dapp::Dimg::GitArtifact.new(repo, **git_artifact_options))
30
- artifacts.concat(generate_git_submodules_artifacts(artifact))
31
+ artifacts.concat(generate_git_embedded_artifacts(artifact))
31
32
  end
32
33
  end
33
34
 
34
- def generate_git_submodules_artifacts(artifact)
35
+ def generate_git_embedded_artifacts(artifact)
35
36
  [].tap do |artifacts|
36
- artifacts.concat(submodules_artifacts = artifact.submodules_artifacts)
37
- artifacts.concat(submodules_artifacts.map(&method(:generate_git_submodules_artifacts)).flatten)
37
+ artifacts.concat(submodules_artifacts = artifact.embedded_artifacts)
38
+ artifacts.concat(submodules_artifacts.map(&method(:generate_git_embedded_artifacts)).flatten)
38
39
  end
39
40
  end
40
41
  end # GitArtifact
@@ -33,6 +33,10 @@ module Dapp
33
33
  end
34
34
  # rubocop:enable Metrics/ParameterLists
35
35
 
36
+ def embedded_artifacts
37
+ [submodules_artifacts, nested_git_directory_artifacts].flatten
38
+ end
39
+
36
40
  def submodules_artifacts
37
41
  commit = dev_mode? ? nil : latest_commit
38
42
  repo.submodules_params(commit,
@@ -41,65 +45,72 @@ module Dapp
41
45
  end
42
46
 
43
47
  def submodule_artifact(submodule_params)
44
- submodule_rel_path = submodule_params[:path]
45
- submodule_repo = begin
46
- GitRepo::Remote.new(repo.dimg, submodule_rel_path,
47
- url: submodule_url(submodule_params[:url])).tap { |r| r.fetch!(submodule_params[:branch]) }
48
- rescue Rugged::InvalidError => e
49
- raise Error::Rugged, code: :incorrect_gitmodules_file, data: { error: e.message }
50
- end
48
+ embedded_artifact(submodule_params)
49
+ rescue Rugged::InvalidError => e
50
+ raise Error::Rugged, code: :incorrect_gitmodules_file, data: { error: e.message }
51
+ end
51
52
 
52
- self.class.new(submodule_repo, submodule_artifact_options(submodule_params))
53
+ def nested_git_directory_artifacts
54
+ return [] unless dev_mode?
55
+ repo
56
+ .nested_git_directories_patches(paths: include_paths_or_cwd, exclude_paths: exclude_paths(true), **diff_patches_options)
57
+ .map(&method(:nested_git_directory_artifact))
53
58
  end
54
59
 
55
- def submodule_url(url)
56
- if url.start_with?('../')
57
- case repo.remote_origin_url_protocol
58
- when :http, :https, :git
59
- uri = URI.parse(repo.remote_origin_url)
60
- uri.path = File.expand_path(File.join(uri.path, url))
61
- uri.to_s
62
- when :ssh
63
- host_with_user, group_and_project = repo.remote_origin_url.split(':', 2)
64
- group_and_project = File.expand_path(File.join('/', group_and_project, url))[1..-1]
65
- [host_with_user, group_and_project].join(':')
60
+ def nested_git_directory_artifact(patch)
61
+ params = {}.tap do |p|
62
+ p[:path] = patch.delta.new_file[:path]
63
+ p[:type] = :local
64
+ end
65
+ embedded_artifact(params)
66
+ end
67
+
68
+ def embedded_artifact(embedded_params)
69
+ embedded_rel_path = embedded_params[:path]
70
+ embedded_repo = begin
71
+ if embedded_params[:type] == :remote
72
+ GitRepo::Remote.new(repo.dimg, embedded_rel_path,
73
+ url: embedded_params[:url]).tap { |r| r.fetch!(embedded_params[:branch]) }
74
+ elsif embedded_params[:type] == :local
75
+ embedded_path = File.join(repo.workdir_path, embedded_params[:path])
76
+ GitRepo::Local.new(repo.dimg, embedded_rel_path, embedded_path)
66
77
  else
67
78
  raise
68
79
  end
69
- else
70
- url
71
80
  end
81
+
82
+ self.class.new(embedded_repo, embedded_artifact_options(embedded_params))
72
83
  end
73
84
 
74
- def submodule_artifact_options(submodule_params)
75
- submodule_rel_path = submodule_params[:path]
85
+ def embedded_artifact_options(embedded_params)
86
+ embedded_rel_path = embedded_params[:path]
76
87
 
77
88
  {}.tap do |options|
78
- options[:name] = repo.dapp.consistent_uniq_slugify("submodule-#{submodule_rel_path}")
79
- options[:cwd] = submodule_inherit_path(cwd, submodule_rel_path).last
80
- options[:to] = File.join(to, submodule_rel_path)
81
- options[:include_paths] = submodule_inherit_paths(include_paths, submodule_rel_path)
82
- options[:exclude_paths] = submodule_inherit_paths(exclude_paths, submodule_rel_path)
89
+ options[:name] = repo.dapp.consistent_uniq_slugify("embedded-#{embedded_rel_path}")
90
+ options[:cwd] = embedded_inherit_path(cwd, embedded_rel_path).last
91
+ options[:to] = File.join(to, embedded_rel_path)
92
+ options[:include_paths] = embedded_inherit_paths(include_paths, embedded_rel_path)
93
+ options[:exclude_paths] = embedded_inherit_paths(exclude_paths, embedded_rel_path)
83
94
  options[:stages_dependencies] = begin
84
95
  stages_dependencies
85
- .map { |stage, paths| [stage, submodule_inherit_paths(paths, submodule_rel_path)] }
96
+ .map { |stage, paths| [stage, embedded_inherit_paths(paths, embedded_rel_path)] }
86
97
  .to_h
87
98
  end
88
- options[:branch] = submodule_params[:branch]
99
+ options[:branch] = embedded_params[:branch]
89
100
  options[:owner] = owner
90
101
  options[:group] = group
91
102
  end
92
103
  end
93
104
 
94
- def submodule_inherit_paths(paths, submodule_rel_path)
105
+ def embedded_inherit_paths(paths, embedded_rel_path)
95
106
  paths
96
- .select { |path| check_path?(submodule_rel_path, path) || check_subpath?(submodule_rel_path, path) }
97
- .map { |path| submodule_inherit_path(path, submodule_rel_path) }
107
+ .select { |path| check_path?(embedded_rel_path, path) || check_subpath?(embedded_rel_path, path) }
108
+ .map { |path| embedded_inherit_path(path, embedded_rel_path) }
98
109
  .flatten
99
110
  .compact
100
111
  end
101
112
 
102
- def submodule_inherit_path(path, submodule_rel_path)
113
+ def embedded_inherit_path(path, embedded_rel_path)
103
114
  path_parts = path.split('/')
104
115
  test_path = nil
105
116
  inherited_paths = []
@@ -107,7 +118,7 @@ module Dapp
107
118
  last_part_path = path_parts.shift
108
119
  test_path = [test_path, last_part_path].compact.join('/')
109
120
 
110
- non_match = !File.fnmatch(test_path, submodule_rel_path, File::FNM_PATHNAME)
121
+ non_match = !File.fnmatch(test_path, embedded_rel_path, File::FNM_PATHNAME)
111
122
  part_for_all = (last_part_path == '**')
112
123
 
113
124
  if non_match || part_for_all
@@ -462,16 +473,23 @@ module Dapp
462
473
 
463
474
  def diff_patches(from_commit, to_commit, paths: include_paths_or_cwd)
464
475
  (@diff_patches ||= {})[[from_commit, to_commit, paths]] ||= begin
465
- options = {}.tap do |opts|
466
- opts[:force_text] = true
467
- if dev_mode?
468
- opts[:include_untracked] = true
469
- opts[:recurse_untracked_dirs] = true
476
+ repo
477
+ .patches(from_commit, to_commit, paths: paths, exclude_paths: exclude_paths(true), **diff_patches_options)
478
+ .select do |patch|
479
+ file_mode = patch.delta.new_file[:mode]
480
+ !(submodule_mode?(file_mode) || # FIXME: https://github.com/libgit2/rugged/issues/727
481
+ nested_git_directory_mode?(file_mode))
470
482
  end
483
+ end
484
+ end
485
+
486
+ def diff_patches_options
487
+ {}.tap do |opts|
488
+ opts[:force_text] = true
489
+ if dev_mode?
490
+ opts[:include_untracked] = true
491
+ opts[:recurse_untracked_dirs] = true
471
492
  end
472
- repo
473
- .patches(from_commit, to_commit, paths: paths, exclude_paths: exclude_paths(true), **options)
474
- .select { |patch| !submodule_mode?(patch.delta.new_file[:mode]) } # FIXME: https://github.com/libgit2/rugged/issues/727
475
493
  end
476
494
  end
477
495
 
@@ -479,6 +497,10 @@ module Dapp
479
497
  mode == 0o160000
480
498
  end
481
499
 
500
+ def nested_git_directory_mode?(mode)
501
+ mode == 0o040000
502
+ end
503
+
482
504
  def include_paths_or_cwd
483
505
  case
484
506
  when !include_paths(true).empty? then include_paths(true)
@@ -530,7 +552,7 @@ module Dapp
530
552
  end
531
553
 
532
554
  def local?
533
- repo.is_a? GitRepo::Own
555
+ repo.is_a? GitRepo::Local
534
556
  end
535
557
  end
536
558
  end
@@ -63,6 +63,10 @@ module Dapp
63
63
  url_protocol(remote_origin_url)
64
64
  end
65
65
 
66
+ def nested_git_directories_patches(*_args)
67
+ raise
68
+ end
69
+
66
70
  def submodules_params(commit, paths: [], exclude_paths: [])
67
71
  raise "Workdir not supported for #{self.class}" if commit.nil?
68
72
 
@@ -82,10 +86,31 @@ module Dapp
82
86
  .map do |_, params|
83
87
  params = params.symbolize_keys
84
88
  params[:branch] = params[:branch].to_s if params.key?(:branch)
89
+ params[:url] = submodule_url(params[:url])
90
+ params[:type] = url_protocol(params[:url]) == :noname ? :local : :remote
85
91
  params
86
92
  end
87
93
  end
88
94
 
95
+ def submodule_url(gitsubmodule_url)
96
+ if gitsubmodule_url.start_with?('../')
97
+ case remote_origin_url_protocol
98
+ when :http, :https, :git
99
+ uri = URI.parse(remote_origin_url)
100
+ uri.path = File.expand_path(File.join(uri.path, gitsubmodule_url))
101
+ uri.to_s
102
+ when :ssh
103
+ host_with_user, group_and_project = remote_origin_url.split(':', 2)
104
+ group_and_project = File.expand_path(File.join('/', group_and_project, gitsubmodule_url))[1..-1]
105
+ [host_with_user, group_and_project].join(':')
106
+ else
107
+ raise
108
+ end
109
+ else
110
+ gitsubmodule_url
111
+ end
112
+ end
113
+
89
114
  # FIXME: Убрать логику исключения путей exclude_paths из данного класса,
90
115
  # FIXME: т.к. большинство методов не поддерживают инвариант
91
116
  # FIXME "всегда выдавать данные с исключенными путями".
@@ -98,16 +123,14 @@ module Dapp
98
123
 
99
124
  def patches(from, to, paths: [], exclude_paths: [], **kwargs)
100
125
  diff(from, to, **kwargs).patches.select do |patch|
101
- delta_new_file = patch.delta.new_file
102
- args = [delta_new_file[:path], paths: paths, exclude_paths: exclude_paths]
103
- if delta_new_file[:mode] == 0o040000 # nested git repository in dev mode
104
- !ignore_directory?(*args)
105
- else
106
- !ignore_path?(*args)
107
- end
126
+ ignore_patch?(patch, paths: paths, exclude_paths: exclude_paths)
108
127
  end
109
128
  end
110
129
 
130
+ def ignore_patch?(patch, paths: [], exclude_paths: [])
131
+ !ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
132
+ end
133
+
111
134
  def entries(commit, paths: [], exclude_paths: [])
112
135
  [].tap do |entries|
113
136
  lookup_commit(commit).tree.walk(:preorder) do |root, entry|
@@ -183,13 +206,6 @@ module Dapp
183
206
  git.lookup(commit)
184
207
  end
185
208
 
186
- def exist?
187
- git
188
- true
189
- rescue Rugged::OSError
190
- false
191
- end
192
-
193
209
  protected
194
210
 
195
211
  attr_reader :manager
@@ -0,0 +1,95 @@
1
+ module Dapp
2
+ module Dimg
3
+ module GitRepo
4
+ class Local < Base
5
+ attr_reader :path
6
+
7
+ def initialize(manager, name, path)
8
+ super(manager, name)
9
+ self.path = path
10
+ end
11
+
12
+ def path=(path)
13
+ @path ||= Pathname(Rugged::Repository.new(path).path)
14
+ rescue Rugged::RepositoryError, Rugged::OSError => _e
15
+ raise Error::Rugged, code: :local_git_repository_does_not_exist, data: { path: path }
16
+ end
17
+
18
+ def workdir_path
19
+ Pathname(git.workdir)
20
+ end
21
+
22
+ def nested_git_directories_patches(paths: [], exclude_paths: [], **kwargs)
23
+ patches(nil, nil, paths: paths, exclude_paths: exclude_paths, **kwargs).select do |patch|
24
+ delta_new_file = patch.delta.new_file
25
+ nested_git_repository_mode?(delta_new_file[:mode])
26
+ end
27
+ end
28
+
29
+ # NOTICE: Параметры {from: nil, to: nil} можно указать только для Own repo.
30
+ # NOTICE: Для Remote repo такой вызов не имеет смысла и это ошибка пользователя класса Remote.
31
+
32
+ def submodules_params(commit, paths: [], exclude_paths: [])
33
+ return super unless commit.nil?
34
+ return [] unless File.file?((gitmodules_file_path = File.join(workdir_path, '.gitmodules')))
35
+
36
+ submodules_params_base(File.read(gitmodules_file_path),
37
+ paths: paths,
38
+ exclude_paths: exclude_paths).each do |submodule_params|
39
+ submodule_path = File.join(workdir_path, submodule_params[:path])
40
+ if git_repo_exist?(submodule_path)
41
+ dapp.log_info("Using local submodule `#{submodule_path}`!")
42
+ submodule_params[:type] = :local
43
+ end
44
+ end
45
+ end
46
+
47
+ def ignore_patch?(patch, paths: [], exclude_paths: [])
48
+ delta_new_file = patch.delta.new_file
49
+ args = [delta_new_file[:path], paths: paths, exclude_paths: exclude_paths]
50
+ if nested_git_repository_mode?(delta_new_file[:mode])
51
+ !ignore_directory?(*args)
52
+ else
53
+ !ignore_path?(*args)
54
+ end
55
+ end
56
+
57
+ def nested_git_repository_mode?(mode)
58
+ mode == 0o040000
59
+ end
60
+
61
+ def diff(from, to, **kwargs)
62
+ if from.nil? and to.nil?
63
+ mid_commit = latest_commit
64
+ diff_obj = super(nil, mid_commit, **kwargs)
65
+ diff_obj.merge! git.lookup(mid_commit).diff_workdir(**kwargs)
66
+ diff_obj
67
+ elsif to.nil?
68
+ git.lookup(from).diff_workdir(**kwargs)
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ def latest_commit(_branch = nil)
75
+ git.head.target_id
76
+ end
77
+
78
+ def lookup_commit(commit)
79
+ super
80
+ rescue Rugged::OdbError, TypeError => _e
81
+ raise Error::Rugged, code: :commit_not_found_in_local_git_repository, data: { commit: commit }
82
+ end
83
+
84
+ protected
85
+
86
+ def git_repo_exist?(path)
87
+ Rugged::Repository.new(path)
88
+ true
89
+ rescue Rugged::RepositoryError, Rugged::OSError => _e
90
+ false
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,63 +1,17 @@
1
1
  module Dapp
2
2
  module Dimg
3
3
  module GitRepo
4
- class Own < Base
4
+ class Own < Local
5
5
  def initialize(manager)
6
- super(manager, 'own')
6
+ super(manager, 'own', nil)
7
7
  end
8
8
 
9
- def exclude_paths
10
- dapp.local_git_artifact_exclude_paths
11
- end
12
-
13
- def workdir_path
14
- Pathname(git.workdir)
15
- end
16
-
17
- def path
18
- @path ||= Pathname(Rugged::Repository.discover(dapp.path.to_s).path)
19
- rescue Rugged::RepositoryError => _e
20
- raise Error::Rugged, code: :local_git_repository_does_not_exist
21
- end
22
-
23
- # NOTICE: Параметры {from: nil, to: nil} можно указать только для Own repo.
24
- # NOTICE: Для Remote repo такой вызов не имеет смысла и это ошибка пользователя класса Remote.
25
-
26
- def submodules_params(commit, paths: [], exclude_paths: [])
27
- return super unless commit.nil?
28
- return [] unless File.file?((gitmodules_file_path = File.join(workdir_path, '.gitmodules')))
29
-
30
- submodules_params_base(File.read(gitmodules_file_path), paths: paths, exclude_paths: exclude_paths)
31
- end
32
-
33
- def diff(from, to, **kwargs)
34
- if from.nil? and to.nil?
35
- mid_commit = latest_commit
36
- diff_obj = super(nil, mid_commit, **kwargs)
37
- diff_obj.merge! git.lookup(mid_commit).diff_workdir(**kwargs)
38
- diff_obj
39
- elsif to.nil?
40
- git.lookup(from).diff_workdir(**kwargs)
41
- else
42
- super
43
- end
44
- end
45
-
46
- def latest_commit(_branch = nil)
47
- git.head.target_id
9
+ def path=(_)
10
+ super(dapp.path.to_s)
48
11
  end
49
12
 
50
- def lookup_commit(commit)
51
- super
52
- rescue Rugged::OdbError, TypeError => _e
53
- raise Error::Rugged, code: :commit_not_found_in_local_git_repository, data: { commit: commit }
54
- end
55
-
56
- def exist?
57
- super
58
- rescue Error::Rugged => e
59
- return false if e.net_status[:code] == :local_git_repository_does_not_exist
60
- raise
13
+ def exclude_paths
14
+ dapp.local_git_artifact_exclude_paths
61
15
  end
62
16
  end
63
17
  end
@@ -27,7 +27,7 @@ module Dapp
27
27
  .reject { |job| ['0', 'false'].include? job.annotations["dapp/recreate"].to_s }
28
28
  .select { |job| all_jobs_names.include? job.name }
29
29
  .each do |job|
30
- log_process("Delete hooks job `#{job.name}`", short: true) do
30
+ log_process("Delete hook job `#{job.name}` (dapp/recreate)", short: true) do
31
31
  kube_delete_job!(job.name, all_pods_specs) unless dry_run?
32
32
  end
33
33
  end
@@ -133,13 +133,18 @@ module Dapp
133
133
  watch_hooks_condition.signal
134
134
  end
135
135
 
136
- release.deploy!
136
+ cmd_res = release.helm_upgrade!
137
+
138
+ if cmd_res.error?
139
+ raise ::Dapp::Error::Command, code: :kube_helm_failed, data: {output: (cmd_res.stdout + cmd_res.stderr).strip}
140
+ else
141
+ watch_hooks_thr.join if !dry_run? && watch_hooks_thr && watch_hooks_thr.alive?
142
+ log_info((cmd_res.stdout + cmd_res.stderr).strip)
143
+ end
137
144
  end
138
145
 
139
146
  deployment_managers.each(&:after_deploy)
140
147
 
141
- watch_hooks_thr.kill if !dry_run? && watch_hooks_thr && watch_hooks_thr.alive?
142
-
143
148
  unless dry_run?
144
149
  begin
145
150
  ::Timeout::timeout(self.options[:timeout] || 300) do
@@ -49,7 +49,7 @@ module Dapp
49
49
  end.to_h
50
50
  end
51
51
 
52
- def deploy!
52
+ def helm_upgrade!
53
53
  args = [
54
54
  name, chart_path, additional_values_options,
55
55
  set_options, upgrade_extra_options
@@ -57,7 +57,9 @@ module Dapp
57
57
 
58
58
  dapp.kubernetes.create_namespace!(namespace) unless dapp.kubernetes.namespace?(namespace)
59
59
 
60
- dapp.shellout! "helm upgrade #{args.join(' ')}", verbose: true
60
+ cmd = dapp.shellout "helm upgrade #{args.join(' ')}"
61
+
62
+ return cmd
61
63
  end
62
64
 
63
65
  def templates
@@ -63,7 +63,7 @@ module Dapp
63
63
  end
64
64
 
65
65
  dimgs = dapp.build_configs.map do |config|
66
- ::Dapp::Dimg::Dimg.new(config: config, dapp: dapp, ignore_git_fetch: true)
66
+ dapp.dimg(config: config, ignore_git_fetch: true)
67
67
  end.uniq do |dimg|
68
68
  dimg.config._name
69
69
  end
@@ -2,6 +2,20 @@ module Dapp
2
2
  module Kube
3
3
  module Kubernetes::Client::Resource
4
4
  class Pod < Base
5
+ # Returns:
6
+ # nil: no such condition yet
7
+ # "True" string: ready
8
+ # "False" string: not ready
9
+ def ready_condition_status
10
+ rd = self.ready_condition
11
+ return nil unless rd
12
+ return rd['status']
13
+ end
14
+
15
+ def ready_condition
16
+ status.fetch('conditions', {}).find {|condition| condition['type'] == 'Ready'}
17
+ end
18
+
5
19
  def container_id(container_name)
6
20
  container_status = spec.fetch('status', {})
7
21
  .fetch('containerStatuses')
@@ -18,7 +18,7 @@ module Dapp
18
18
  _, container_state_data = pod.container_state(name)
19
19
  return if @processed_containers_ids.include? container_state_data['containerID']
20
20
 
21
- pod_manager.wait_till_running!
21
+ pod_manager.wait_till_launched!
22
22
 
23
23
  pod = Kubernetes::Client::Resource::Pod.new(dapp.kubernetes.pod(pod_manager.name))
24
24
  container_state, container_state_data = pod.container_state(name)
@@ -22,6 +22,8 @@ module Dapp
22
22
  @deployment_before_deploy = Kubernetes::Client::Resource::Deployment.new(dapp.kubernetes.replace_deployment!(name, new_spec))
23
23
  end
24
24
  end
25
+
26
+ @deploy_began_at = Time.now
25
27
  end
26
28
 
27
29
  def after_deploy
@@ -116,7 +118,11 @@ module Dapp
116
118
  known_log_timestamps_by_pod_and_container[pod.name][container_name] ||= Set.new
117
119
 
118
120
  since_time = nil
119
- since_time = @deployed_at.utc.iso8601(9) if @deployed_at
121
+ # Если под еще не перешел в состоянии готовности, то можно вывести все логи которые имеются.
122
+ # Иначе выводим только новые логи с момента начала текущей сессии деплоя.
123
+ if [nil, "True"].include? pod.ready_condition_status
124
+ since_time = @deploy_began_at.utc.iso8601(9) if @deploy_began_at
125
+ end
120
126
 
121
127
  log_lines_by_time = []
122
128
  begin
@@ -147,34 +153,8 @@ module Dapp
147
153
  end
148
154
  end
149
155
 
150
- ready_condition = pod.status.fetch('conditions', {}).find {|condition| condition['type'] == 'Ready'}
151
- next if (not ready_condition) or (ready_condition['status'] == 'True')
152
-
153
- if ready_condition['reason'] == 'ContainersNotReady'
154
- Array(pod.status['containerStatuses']).each do |container_status|
155
- next if container_status['ready']
156
-
157
- waiting_reason = container_status.fetch('state', {}).fetch('waiting', {}).fetch('reason', nil)
158
- case waiting_reason
159
- when 'ImagePullBackOff', 'ErrImagePull'
160
- raise Kubernetes::Error::Base,
161
- code: :image_not_found,
162
- data: {pod_name: pod.name,
163
- reason: waiting_reason,
164
- message: container_status['state']['waiting']['message']}
165
- when 'CrashLoopBackOff'
166
- raise Kubernetes::Error::Base,
167
- code: :container_crash,
168
- data: {pod_name: pod.name,
169
- reason: waiting_reason,
170
- message: container_status['state']['waiting']['message']}
171
- end
172
- end
173
- else
174
- dapp.with_log_indent do
175
- dapp.log_warning("#{dapp.log_time}Unknown pod readiness condition reason '#{ready_condition['reason']}': #{ready_condition}", stream: dapp.service_stream)
176
- end
177
- end
156
+ pod_manager = Kubernetes::Manager::Pod.new(dapp, pod.name)
157
+ pod_manager.check_readiness_condition_if_available!(pod)
178
158
  end # with_log_indent
179
159
  end # rs_pods.each
180
160
  end # with_log_indent
@@ -9,10 +9,44 @@ module Dapp
9
9
  end
10
10
  end
11
11
 
12
- def wait_till_running!
12
+ def check_readiness_condition_if_available!(pod)
13
+ return if [nil, "True"].include? pod.ready_condition_status
14
+
15
+ if pod.ready_condition['reason'] == 'ContainersNotReady'
16
+ [*Array(pod.status["initContainerStatuses"]), *Array(pod.status["containerStatuses"])].each do |container_status|
17
+ next if container_status['ready']
18
+
19
+ waiting_reason = container_status.fetch('state', {}).fetch('waiting', {}).fetch('reason', nil)
20
+ case waiting_reason
21
+ when 'ImagePullBackOff', 'ErrImagePull'
22
+ raise Kubernetes::Error::Default,
23
+ code: :bad_image,
24
+ data: {pod_name: pod.name,
25
+ reason: waiting_reason,
26
+ message: container_status['state']['waiting']['message']}
27
+ when 'CrashLoopBackOff'
28
+ raise Kubernetes::Error::Default,
29
+ code: :container_crash,
30
+ data: {pod_name: pod.name,
31
+ reason: waiting_reason,
32
+ message: container_status['state']['waiting']['message']}
33
+ end
34
+ end
35
+ else
36
+ dapp.with_log_indent do
37
+ dapp.log_warning("#{dapp.log_time}Unknown pod readiness condition reason '#{pod.ready_condition['reason']}': #{pod.ready_condition}", stream: dapp.service_stream)
38
+ end
39
+ end
40
+ end
41
+
42
+ def wait_till_launched!
13
43
  loop do
14
44
  pod = Kubernetes::Client::Resource::Pod.new(dapp.kubernetes.pod(name))
15
- break if pod.phase == 'Running'
45
+
46
+ break if pod.phase != "Pending"
47
+
48
+ check_readiness_condition_if_available!(pod)
49
+
16
50
  sleep 0.1
17
51
  end
18
52
  end
@@ -1,4 +1,4 @@
1
1
  module Dapp
2
- VERSION = "0.24.3"
2
+ VERSION = "0.24.4"
3
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.3
4
+ version: 0.24.4
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-01-18 00:00:00.000000000 Z
11
+ date: 2018-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-shellout
@@ -600,6 +600,7 @@ files:
600
600
  - lib/dapp/dimg/dapp/command/tag.rb
601
601
  - lib/dapp/dimg/dapp/dapp.rb
602
602
  - lib/dapp/dimg/dapp/dappfile.rb
603
+ - lib/dapp/dimg/dapp/dimg.rb
603
604
  - lib/dapp/dimg/dimg.rb
604
605
  - lib/dapp/dimg/dimg/git_artifact.rb
605
606
  - lib/dapp/dimg/dimg/path.rb
@@ -624,6 +625,7 @@ files:
624
625
  - lib/dapp/dimg/filelock.rb
625
626
  - lib/dapp/dimg/git_artifact.rb
626
627
  - lib/dapp/dimg/git_repo/base.rb
628
+ - lib/dapp/dimg/git_repo/local.rb
627
629
  - lib/dapp/dimg/git_repo/own.rb
628
630
  - lib/dapp/dimg/git_repo/remote.rb
629
631
  - lib/dapp/dimg/image/argument.rb