dapp 0.18.2 → 0.18.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8a752ddf15e0189c19374288fa4c47dde8c51052aa7a341d6c687456510f7d8
4
- data.tar.gz: 0646f23204bca59262e9811ea034fe9c7cd6711be864e95901f84c792e7893bd
3
+ metadata.gz: 767fd53a4c1d7206a3f9e7f94076eea3c21fb99f9221b8d05648f4798736a699
4
+ data.tar.gz: be17e4e371969d98f96a7d7c1b79768b35bd277e262c0fa0295ce17d0db890f8
5
5
  SHA512:
6
- metadata.gz: d381c0f3c52d605a5efdfc2af90293cbaec8209d183520b28b1460a3b12c80ed79de53d7fae0dbaa2ca6262fb4e4f3333faaea2bbe66909de93d8dbb17b9e4e6
7
- data.tar.gz: c782aaa9b056b70e1575f8c1cdad640782c7f58cf56d9cc83a13fe96c4ba80ad7c2bfb70a421c8a606a9384666105376225634dcdd6af0097fdc9d1d2de4a33a
6
+ metadata.gz: 6855db575b0ae8392f2c718fc226aa2d7c849623ecce99ca0331b9f7fd1e353ddf894e53345acd3a7e0da48469ea6db2b7168fe6d2c782bcefe35df73b844bcf
7
+ data.tar.gz: f71e683cb58fc85bfdb96997dfee161dc77e021e8a554ad8bc54f12a59c1a93ce404a747eea85382abd536ef104a679a2af9e6e5ebc3f92013af87c512aff0bd
data/config/en/common.yml CHANGED
@@ -38,6 +38,7 @@ en:
38
38
  state:
39
39
  using_cache: '[USING CACHE]'
40
40
  not_present: '[NOT PRESENT]'
41
+ rebuild: '[REBUILD]'
41
42
  build: '[BUILD]'
42
43
  push: '[PUSH]'
43
44
  pull: '[PULL]'
@@ -14,8 +14,8 @@ en:
14
14
  incorrect: "Dappfile with `%{error}`:\n%{message}"
15
15
  build:
16
16
  from_image_required: 'Missing from_image!'
17
- image_already_untagged: "Image `%{name}` already untagged!"
18
- image_not_exist: "Image `%{name}` not exist!"
17
+ image_already_untagged: "Image `%{name}` untagged already!"
18
+ image_not_exist: "Image `%{name}` doesn't exist!"
19
19
  built_id_not_defined: '`from.built_id` not defined!'
20
20
  from_image_not_found: 'Image `%{name}` not found!'
21
21
  unsupported_patch_format: "Unsupported patch format:\n\n%{patch}"
@@ -32,23 +32,24 @@ en:
32
32
  secret_key_not_found: "Secret key not found in %{not_found_in}!"
33
33
  minikube_not_found: "Minikube not found: install minikube (https://github.com/kubernetes/minikube/releases)!"
34
34
  minikube_not_started: "Minikube not started!"
35
- project_helm_chart_not_found: "Project helm chart `%{path}` not found!"
36
35
  helm_not_found: "Helm not found: install helm (https://github.com/kubernetes/helm/blob/master/docs/install.md)"
37
- helm_release_not_exist: "Helm release `%{name}` not exist!"
36
+ helm_template_plugin_not_installed: "Helm plugin `template` isn't installed: run command `helm plugin install https://github.com/technosophos/helm-template`"
37
+ helm_release_not_exist: "Helm release `%{name}` doesn't exist!"
38
+ no_helm_chart_spec_name: "Bad name `%{name}` in helm chart spec %{path}:\n%{raw_spec}"
38
39
  file_not_exist: "File `%{path}` doesn't exist!"
39
40
  helm_directory_not_exist: "Helm directory doesn't exist in project!"
40
41
  values_file_not_found: "Values file `%{path}` not found!"
41
42
  secret_file_not_found: "Secret file `%{path}` not found!"
42
43
  secret_file_empty: "Secret file `%{path}` can't be empty!"
43
- user_containers_detected: "User containers have been using images!\n%{ids}"
44
+ user_containers_detected: "User containers are using these images:\n%{ids}"
44
45
  incorrect_yaml_structure: "Incorrect YAML structure in `%{path}`!"
45
46
  editor_not_found: "Editor not found!"
46
47
  dapp:
47
48
  no_such_dimg: "No such dimg: `%{dimgs_patterns}`!"
48
49
  no_such_app: "No such app: `%{apps_patterns}`!"
49
50
  dappfile_not_found: "Dappfile not found!"
50
- cannot_run_ssh_agent: "Cannot run ssh-agent"
51
- ssh_key_not_found: "Ssh key `%{path}` not exist!"
51
+ cannot_run_ssh_agent: "Can't run ssh-agent!"
52
+ ssh_key_not_found: "Ssh key `%{path}` doesn't exist!"
52
53
  docker_not_found: "Docker not found!"
53
54
  docker_version: "Required docker version (`%{version}`): `%{min_version}` <= VERSION <= `%{max_version}`!"
54
55
  dapp_config_file_incorrect: "%{message}"
@@ -74,13 +75,13 @@ en:
74
75
  docker_from_incorrect: "`docker.from` has incorrect value `%{name}`!"
75
76
  docker_artifact_unsupported_directive: "`artifact.docker` supports only `from` subdirective!"
76
77
  stage_artifact_not_associated: "Artifact not associated with any stage: expected `before` or `after` attribute!"
77
- stage_artifact_double_associate: "Cannot use `%{stage}` stage for artifact, already used in `%{conflict_stage}` stage!"
78
+ stage_artifact_double_associate: "Can't use `%{stage}` stage for artifact; already used in `%{conflict_stage}` stage!"
78
79
  stage_artifact_not_supported_associated_stage: "Bad artifact stage `%{stage}`!"
79
80
  git_artifact_remote_branch_with_commit: "Remote git repo: use `commit` or `branch` directive!"
80
81
  artifact_conflict: "Conflict between artifacts paths!"
81
82
  scratch_unsupported_directive: "Scratch dimg has unsupported directive `%{directive}`!"
82
83
  scratch_artifact_required: "Scratch dimg without artifacts!"
83
- scratch_artifact_associated: "Scratch artifact cannot be associated: not expected `before`/`after` attribute!"
84
+ scratch_artifact_associated: "Scratch artifact can't be associated: not expected `before`/`after` attribute!"
84
85
  scratch_artifact_docker_from: "Scratch artifact must have directive `docker.from`!"
85
86
  unsupported_scale_value: "Define unsupported scale value `%{value}`!"
86
87
  app_name_required: 'App name required!'
@@ -90,8 +91,8 @@ en:
90
91
  app_bootstrap_dimg_not_found: "Not found dimg `%{dimg}` for app.bootstrap!"
91
92
  app_before_apply_job_dimg_not_defined: "Not defined dimg for app.before_apply_job!"
92
93
  app_before_apply_job_dimg_not_found: "Not found dimg `%{dimg}` for app.before_apply_job!"
93
- unsupported_port_number: 'Port number `%{number}` doesn`t support!'
94
- unsupported_target_number: 'Target number `%{number}` doesn`t support!'
94
+ unsupported_port_number: "Port number `%{number}` isn't supported!"
95
+ unsupported_target_number: "Target number `%{number}` isn't supported!"
95
96
  app_name_incorrect: "App has incorrect name `%{value}`: doesn't match regex `%{pattern}`!"
96
97
  namespace_name_incorrect: "Namespace has incorrect name `%{value}`: doesn't match regex `%{pattern}`!"
97
98
  deployment_bootstrap_dimg_not_defined: "Not defined dimg for deployment.bootstrap!"
@@ -99,13 +100,13 @@ en:
99
100
  deployment_before_apply_job_dimg_not_defined: "Not defined dimg for deployment.before_apply_job!"
100
101
  deployment_before_apply_job_dimg_not_found: "Not found dimg `%{dimg}` for deployment.before_apply_job!"
101
102
  chef:
102
- stage_checksum_not_calculated: "Chef stage `%{stage}` checksum is not calculated yet, run build first"
103
- stage_path_overlap: "Cannot install `%{cookbook}` cookbook's path %{from} into %{to}: already exists"
103
+ stage_checksum_not_calculated: "Chef stage `%{stage}` checksum isn't calculated yet, run build first!"
104
+ stage_path_overlap: "Can't install `%{cookbook}` cookbook's path %{from} into %{to} already exists!"
104
105
  builder_cookbook_not_found: "Dapp cookbook directory not found at %{path}"
105
106
  berksfile_absolute_path_forbidden: "Absolute paths in Berksfile are not allowed (cookbook `%{cookbook}`, path: `%{path}`)"
106
107
  registry:
107
108
  no_such_dimg: 'Registry `%{registry}`: no such dimg in registry!'
108
- authenticate_type_not_supported: 'Registry `%{registry}`: authenticate type not supported!'
109
+ authenticate_type_not_supported: 'Registry `%{registry}`: authenticate type is not supported!'
109
110
  page_not_found: "Registry `%{registry}`: page `%{url}` not found!"
110
111
  user_not_authorized: 'Registry `%{registry}`: user not authorized!'
111
112
  rugged:
@@ -118,7 +119,7 @@ en:
118
119
  rugged_protocol_not_supported: "Rugged has been compiled without support for `%{protocol}`.\nGit repositories will not be reachable via `%{protocol}` (`%{url}`).\nRugged.features should include `%{protocol}`."
119
120
  submodule_not_supported: "Git submodules not supported! (`%{path}`)"
120
121
  lock:
121
- timeout: "Could not obtain lock for `%{name}` within %{timeout} seconds"
122
+ timeout: "Could not obtain lock for `%{name}` within %{timeout} seconds!"
122
123
  app:
123
124
  namespace_not_found: "App `%{name}`: namespace `%{namespace}` not found!"
124
125
  namespace_not_defined: "App `%{name}`: namespace not defined!"
@@ -132,5 +133,5 @@ en:
132
133
  kube_config_not_found: "Kube config `%{path}` not found!"
133
134
  kube_server_connection_refused: "Kube server `%{url}` connection refused: %{error}"
134
135
  secret:
135
- bad_data: "Data `%{data}` can't be decrypted: check encryption key and data."
136
+ bad_data: "Data `%{data}` can't be decrypted: check encryption key and data!"
136
137
  key_length_too_short: "Encryption key isn't valid (required size %{required_size} bytes)!"
data/lib/dapp.rb CHANGED
@@ -135,6 +135,8 @@ require 'dapp/kube/cli/command/kube/secret_regenerate'
135
135
  require 'dapp/kube/cli/command/kube/secret_edit'
136
136
  require 'dapp/kube/cli/command/kube/minikube_setup'
137
137
  require 'dapp/kube/cli/command/kube/chart_create'
138
+ require 'dapp/kube/cli/command/kube/render'
139
+ require 'dapp/kube/cli/command/kube/lint'
138
140
  require 'dapp/kube/cli/cli'
139
141
  require 'dapp/kube/dapp/command/common'
140
142
  require 'dapp/kube/dapp/command/deploy'
@@ -146,6 +148,8 @@ require 'dapp/kube/dapp/command/secret_regenerate'
146
148
  require 'dapp/kube/dapp/command/secret_edit'
147
149
  require 'dapp/kube/dapp/command/minikube_setup'
148
150
  require 'dapp/kube/dapp/command/chart_create'
151
+ require 'dapp/kube/dapp/command/render'
152
+ require 'dapp/kube/dapp/command/lint'
149
153
  require 'dapp/kube/dapp/dapp'
150
154
  require 'dapp/dimg'
151
155
  require 'dapp/dimg/builder'
@@ -123,6 +123,16 @@ module Dapp
123
123
  end
124
124
  end
125
125
 
126
+ def service_stream
127
+ @@service_stream ||= begin
128
+ fd = IO.sysopen("/tmp/dapp-service.log", "a")
129
+
130
+ stream = IO.new(fd)
131
+ stream.sync = true
132
+ stream
133
+ end
134
+ end
135
+
126
136
  protected
127
137
 
128
138
  attr_writer :log_indent_size
@@ -49,6 +49,7 @@ module Dapp
49
49
 
50
50
  def build!
51
51
  prev_stage.build! if prev_stage
52
+ renew if should_be_renewed?
52
53
  image_build unless empty?
53
54
  image_introspect if image_should_be_introspected?
54
55
  end
@@ -86,7 +87,7 @@ module Dapp
86
87
  image.add_service_change_label dapp: dimg.stage_dapp_label
87
88
  image.add_service_change_label 'dapp-version'.to_sym => ::Dapp::VERSION
88
89
  image.add_service_change_label 'dapp-cache-version'.to_sym => ::Dapp::BUILD_CACHE_VERSION
89
- image.add_service_change_label 'dapp-dev-mode'.to_sym => true if dimg.dev_mode?
90
+ image.add_service_change_label 'dapp-dev-mode'.to_sym => true if dimg.dev_mode_cache?
90
91
 
91
92
  if dimg.dapp.ssh_auth_sock
92
93
  image.add_volume "#{dimg.dapp.ssh_auth_sock}:/tmp/dapp-ssh-agent"
@@ -189,6 +190,10 @@ module Dapp
189
190
  []
190
191
  end
191
192
 
193
+ def dependencies_discard
194
+ @dependencies = nil
195
+ end
196
+
192
197
  def artifact?
193
198
  false
194
199
  end
@@ -213,6 +218,22 @@ module Dapp
213
218
 
214
219
  protected
215
220
 
221
+ def renew
222
+ dependencies_discard
223
+ image_reset
224
+ image_untag! if image_should_be_untagged?
225
+ end
226
+
227
+ def image_reset
228
+ Image::Stage.image_reset(image_name)
229
+ @image = nil
230
+ end
231
+
232
+ def image_untag!
233
+ return if dimg.dapp.dry_run?
234
+ image.untag!
235
+ end
236
+
216
237
  def image_build
217
238
  prepare_image if image_should_be_prepared?
218
239
  log_image_build do
@@ -234,9 +255,33 @@ module Dapp
234
255
  (!image.built? && !should_be_not_present? || image_should_be_introspected?) && !dimg.dapp.dry_run?
235
256
  end
236
257
 
258
+ def should_be_renewed?
259
+ current_or_related_image_should_be_untagged?
260
+ end
261
+
262
+ def image_should_be_untagged?
263
+ image.tagged? && current_or_related_image_should_be_untagged?
264
+ end
265
+
266
+ def current_or_related_image_should_be_untagged?
267
+ @current_or_related_image_should_be_untagged ||= begin
268
+ image_should_be_untagged_condition || begin
269
+ if prev_stage.nil?
270
+ false
271
+ else
272
+ prev_stage.current_or_related_image_should_be_untagged?
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ def image_should_be_untagged_condition
279
+ false
280
+ end
281
+
237
282
  def should_be_not_present?
238
283
  return false if next_stage.nil?
239
- next_stage.image.tagged? || next_stage.should_be_not_present?
284
+ !current_or_related_image_should_be_untagged? && (next_stage.image.tagged? || next_stage.should_be_not_present?)
240
285
  end
241
286
 
242
287
  def image_name
@@ -35,6 +35,11 @@ module Dapp
35
35
  end
36
36
  end
37
37
 
38
+ def renew
39
+ @commits = {}
40
+ super
41
+ end
42
+
38
43
  protected
39
44
 
40
45
  def should_not_be_detailed?
@@ -14,6 +14,13 @@ module Dapp
14
14
  def empty?
15
15
  dimg.git_artifacts.empty? || super
16
16
  end
17
+
18
+ def image_should_be_untagged_condition
19
+ return false unless image.tagged?
20
+ dimg.git_artifacts.any? do |git_artifact|
21
+ !git_artifact.repo.commit_exists? image.labels["dapp-git-#{git_artifact.paramshash}-commit"]
22
+ end
23
+ end
17
24
  end # GADependenciesBase
18
25
  end # Stage
19
26
  end # Build
@@ -8,7 +8,7 @@ module Dapp
8
8
  end
9
9
 
10
10
  def signature
11
- @signature ||= hashsum [*dependencies.flatten, change_options]
11
+ hashsum [*dependencies.flatten, change_options]
12
12
  end
13
13
 
14
14
  def image
@@ -6,9 +6,10 @@ module Dapp
6
6
  module Logging
7
7
  def log_image_build
8
8
  case
9
- when image.built? then log_state(:using_cache)
10
- when should_be_not_present? then log_state(:not_present)
11
- when dimg.dapp.dry_run? then log_state(:build, styles: { status: :success })
9
+ when dimg.dapp.dry_run? && image_should_be_untagged? then log_state(:rebuild, styles: { status: :success })
10
+ when image.built? then log_state(:using_cache)
11
+ when should_be_not_present? then log_state(:not_present)
12
+ when dimg.dapp.dry_run? then log_state(:build, styles: { status: :success })
12
13
  else yield
13
14
  end
14
15
  ensure
@@ -21,7 +21,11 @@ module Dapp
21
21
 
22
22
  def changes_size_since_g_a_pre_setup_patch
23
23
  dimg.git_artifacts.map do |git_artifact|
24
- git_artifact.patch_size(prev_g_a_stage.layer_commit(git_artifact), git_artifact.latest_commit)
24
+ if git_artifact.repo.commit_exists? prev_g_a_stage.layer_commit(git_artifact)
25
+ git_artifact.patch_size(prev_g_a_stage.layer_commit(git_artifact), git_artifact.latest_commit)
26
+ else
27
+ 0
28
+ end
25
29
  end.reduce(0, :+)
26
30
  end
27
31
  end # GAPostSetupPatchDependencies
@@ -70,6 +70,11 @@ BANNER
70
70
  long: '--use-system-tar',
71
71
  boolean: true,
72
72
  default: false
73
+
74
+ option :force_save_cache,
75
+ long: '--force-save-cache',
76
+ boolean: true,
77
+ default: false
73
78
  end
74
79
  end
75
80
  end
@@ -42,7 +42,7 @@ module Dapp
42
42
  end
43
43
 
44
44
  def after_stages_build!
45
- return unless last_stage.image.built? || dev_mode?
45
+ return unless last_stage.image.built? || dev_mode_cache?
46
46
  last_stage.save_in_cache!
47
47
  artifacts.each { |artifact| artifact.last_stage.save_in_cache! }
48
48
  end
@@ -152,8 +152,12 @@ module Dapp
152
152
  dapp.dev_mode?
153
153
  end
154
154
 
155
+ def dev_mode_cache?
156
+ dev_mode? || !!dapp.options[:force_save_cache]
157
+ end
158
+
155
159
  def build_cache_version
156
- [::Dapp::BUILD_CACHE_VERSION, dev_mode? ? 1 : 0]
160
+ [::Dapp::BUILD_CACHE_VERSION, dev_mode_cache? ? 1 : 0]
157
161
  end
158
162
 
159
163
  def introspect_image!(image:, options:)
@@ -6,8 +6,18 @@ module Dapp
6
6
  attr_reader :name
7
7
  attr_reader :dapp
8
8
 
9
- def self.image_by_name(name:, **kwargs)
10
- (@images ||= {})[name] ||= new(name: name, **kwargs)
9
+ class << self
10
+ def image_by_name(name:, **kwargs)
11
+ images[name] ||= new(name: name, **kwargs)
12
+ end
13
+
14
+ def image_reset(name)
15
+ images.delete(name)
16
+ end
17
+
18
+ def images
19
+ @images ||= {}
20
+ end
11
21
  end
12
22
 
13
23
  def initialize(name:, dapp:, from: nil)
@@ -1,14 +1,14 @@
1
1
  module Dapp::Kube::CLI
2
2
  module Command
3
3
  class Kube < ::Dapp::CLI
4
- SUBCOMMANDS = ['secret generate', 'secret key generate', 'secret regenerate', 'deploy', 'dismiss', 'secret extract', 'secret edit', 'minikube setup', 'chart create'].freeze
4
+ SUBCOMMANDS = ['secret generate', 'secret key generate', 'secret regenerate', 'deploy', 'dismiss', 'secret extract', 'secret edit', 'minikube setup', 'chart create', 'render', 'lint'].freeze
5
5
 
6
6
  banner <<BANNER.freeze
7
7
  Usage: dapp kube subcommand [subcommand options]
8
8
 
9
9
  Available subcommands: (for details, dapp kube SUB-COMMAND --help)
10
10
 
11
- dapp kube deploy [options] REPO
11
+ dapp kube deploy [options] [REPO]
12
12
  dapp kube dismiss [options]
13
13
  dapp kube secret key generate [options]
14
14
  dapp kube secret generate [FILE_PATH] [options]
@@ -17,6 +17,8 @@ Available subcommands: (for details, dapp kube SUB-COMMAND --help)
17
17
  dapp kube secret edit [FILE_PATH] [options]
18
18
  dapp kube minikube setup
19
19
  dapp kube chart create [options]
20
+ dapp kube render [options] [REPO]
21
+ dapp kube lint [options] [REPO]
20
22
 
21
23
  Options:
22
24
  BANNER
@@ -0,0 +1,53 @@
1
+ module Dapp::Kube::CLI::Command
2
+ class Kube < ::Dapp::CLI
3
+ class Lint < Base
4
+ banner <<BANNER.freeze
5
+ Usage:
6
+
7
+ dapp kube lint [options] [REPO]
8
+
9
+ Options:
10
+ BANNER
11
+
12
+ option :namespace,
13
+ long: '--namespace NAME',
14
+ default: nil
15
+
16
+ option :image_version,
17
+ long: '--image-version IMAGE_VERSION',
18
+ default: 'latest'
19
+
20
+ option :helm_set_options,
21
+ long: '--set STRING_ARRAY',
22
+ default: [],
23
+ proc: proc { |v| composite_options(:helm_set) << v }
24
+
25
+ option :helm_values_options,
26
+ long: '--values FILE_PATH',
27
+ default: [],
28
+ proc: proc { |v| composite_options(:helm_values) << v }
29
+
30
+ option :helm_secret_values_options,
31
+ long: '--secret-values FILE_PATH',
32
+ default: [],
33
+ proc: proc { |v| composite_options(:helm_secret_values) << v }
34
+
35
+ def run(argv = ARGV)
36
+ self.class.parse_options(self, argv)
37
+
38
+ run_dapp_command(nil, options: cli_options) do |dapp|
39
+ repo = if not cli_arguments[0].nil?
40
+ self.class.required_argument(self, 'repo')
41
+ else
42
+ dapp.name
43
+ end
44
+
45
+ dapp.options[:repo] = repo
46
+
47
+ dapp.public_send(run_method)
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,55 @@
1
+ module Dapp::Kube::CLI::Command
2
+ class Kube < ::Dapp::CLI
3
+ class Render < Base
4
+ banner <<BANNER.freeze
5
+ Usage:
6
+
7
+ dapp kube render [options] [REPO]
8
+
9
+ Options:
10
+ BANNER
11
+ option :namespace,
12
+ long: '--namespace NAME',
13
+ default: nil
14
+
15
+ option :image_version,
16
+ long: '--image-version IMAGE_VERSION',
17
+ default: 'latest'
18
+
19
+ option :tmp_dir_prefix,
20
+ long: '--tmp-dir-prefix PREFIX',
21
+ description: 'Tmp directory prefix (/tmp by default). Used for build process service directories.'
22
+
23
+ option :helm_set_options,
24
+ long: '--set STRING_ARRAY',
25
+ default: [],
26
+ proc: proc { |v| composite_options(:helm_set) << v }
27
+
28
+ option :helm_values_options,
29
+ long: '--values FILE_PATH',
30
+ default: [],
31
+ proc: proc { |v| composite_options(:helm_values) << v }
32
+
33
+ option :helm_secret_values_options,
34
+ long: '--secret-values FILE_PATH',
35
+ default: [],
36
+ proc: proc { |v| composite_options(:helm_secret_values) << v }
37
+
38
+ def run(argv = ARGV)
39
+ self.class.parse_options(self, argv)
40
+
41
+ run_dapp_command(nil, options: cli_options) do |dapp|
42
+ repo = if not cli_arguments[0].nil?
43
+ self.class.required_argument(self, 'repo')
44
+ else
45
+ dapp.name
46
+ end
47
+
48
+ dapp.options[:repo] = repo
49
+
50
+ dapp.public_send(run_method)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -3,6 +3,138 @@ module Dapp
3
3
  module Dapp
4
4
  module Command
5
5
  module Common
6
+ def helm_release
7
+ kube_check_helm!
8
+ kube_check_helm_template_plugin!
9
+ kube_check_helm_chart!
10
+
11
+ repo = option_repo
12
+ image_version = options[:image_version]
13
+ validate_repo_name!(repo)
14
+ validate_tag_name!(image_version)
15
+
16
+ with_kube_tmp_chart_dir do
17
+ kube_copy_chart
18
+ kube_helm_decode_secrets
19
+ kube_generate_helm_chart_tpl
20
+
21
+ release = Helm::Release.new(
22
+ self,
23
+ name: kube_release_name,
24
+ repo: repo,
25
+ image_version: image_version,
26
+ namespace: kube_namespace,
27
+ chart_path: kube_chart_path_for_helm,
28
+ set: self.options[:helm_set_options],
29
+ values: [*kube_values_paths, *kube_tmp_chart_secret_values_paths],
30
+ deploy_timeout: self.options[:timeout] || 300
31
+ )
32
+
33
+ yield release
34
+ end
35
+ end
36
+
37
+ def kube_check_helm_chart!
38
+ raise Error::Command, code: :helm_directory_not_exist, data: { path: kube_chart_path } unless kube_chart_path.exist?
39
+ end
40
+
41
+ def kube_check_helm_template_plugin!
42
+ unless shellout!("helm plugin list | awk '{print $1}'").stdout.lines.map(&:strip).any? { |plugin| plugin == 'template' }
43
+ raise Error::Command, code: :helm_template_plugin_not_installed, data: { path: kube_chart_path }
44
+ end
45
+ end
46
+
47
+ def kube_copy_chart
48
+ FileUtils.cp_r("#{kube_chart_path}/.", kube_chart_path_for_helm)
49
+ end
50
+
51
+ def kube_helm_decode_secrets
52
+ if secret.nil?
53
+ log_warning(desc: {
54
+ code: :dapp_secret_key_not_found,
55
+ data: {not_found_in: secret_key_not_found_in.join(', ')}
56
+ }) if !kube_secret_values_paths.empty? || kube_chart_secret_path.directory?
57
+ end
58
+
59
+ kube_helm_decode_secret_files
60
+ kube_helm_decode_secret_values
61
+ end
62
+
63
+ def kube_helm_decode_secret_values
64
+ kube_secret_values_paths.each_with_index do |secret_values_file, index|
65
+ decoded_data = kube_helm_decode_json(secret, yaml_load_file(secret_values_file))
66
+ kube_tmp_chart_secret_values_paths[index].write(decoded_data.to_yaml)
67
+ end
68
+ end
69
+
70
+ def kube_helm_decode_secret_files
71
+ return unless kube_chart_secret_path.directory?
72
+ Dir.glob(kube_chart_secret_path.join('**/*')).each do |entry|
73
+ next if File.directory?(entry)
74
+
75
+ secret_relative_path = Pathname(entry).subpath_of(kube_chart_secret_path)
76
+
77
+ if secret.nil?
78
+ File.open(kube_tmp_chart_secret_path(secret_relative_path), 'wb:ASCII-8BIT', 0600) {|f| f.write ""}
79
+ else
80
+ kube_secret_file_validate!(entry)
81
+ secret_data = secret.extract(IO.binread(entry).chomp("\n"))
82
+ File.open(kube_tmp_chart_secret_path(secret_relative_path), 'wb:ASCII-8BIT', 0600) {|f| f.write secret_data}
83
+ end
84
+ end
85
+ end
86
+
87
+ def kube_generate_helm_chart_tpl
88
+ cont = <<-EOF
89
+ {{/* vim: set filetype=mustache: */}}
90
+
91
+ {{- define "dimg" -}}
92
+ {{- if (ge (len (index .)) 2) -}}
93
+ {{- $name := index . 0 -}}
94
+ {{- $context := index . 1 -}}
95
+ {{- printf "%v:%v-%v" $context.Values.global.dapp.repo $name $context.Values.global.dapp.image_version -}}
96
+ {{- else -}}
97
+ {{- $context := index . 0 -}}
98
+ {{- printf "%v:%v" $context.Values.global.dapp.repo $context.Values.global.dapp.image_version -}}
99
+ {{- end -}}
100
+ {{- end -}}
101
+
102
+ {{- define "dapp_secret_file" -}}
103
+ {{- $relative_file_path := index . 0 -}}
104
+ {{- $context := index . 1 -}}
105
+ {{- $context.Files.Get (print "#{kube_tmp_chart_secret_path.subpath_of(kube_chart_path_for_helm)}/" $relative_file_path) -}}
106
+ {{- end -}}
107
+ EOF
108
+ kube_chart_path_for_helm('templates/_dapp_helpers.tpl').write(cont)
109
+ end
110
+
111
+ def kube_tmp_chart_secret_path(*path)
112
+ kube_chart_path_for_helm('decoded-secret', *path).tap { |p| p.parent.mkpath }
113
+ end
114
+
115
+ def kube_values_paths
116
+ self.options[:helm_values_options].map { |p| Pathname(p).expand_path }.each do |f|
117
+ raise Error::Command, code: :values_file_not_found, data: { path: f } unless f.file?
118
+ end
119
+ end
120
+
121
+ def kube_tmp_chart_secret_values_paths
122
+ @kube_tmp_chart_secret_values_paths ||= kube_secret_values_paths.each_with_index.map { |f, i| kube_chart_path_for_helm( "decoded-secret-values-#{i}.yaml") }
123
+ end
124
+
125
+ def kube_secret_values_paths
126
+ @kube_chart_secret_values_files ||= [].tap do |files|
127
+ files << kube_chart_secret_values_path if kube_chart_secret_values_path.file?
128
+ files.concat(options[:helm_secret_values_options].map { |p| Pathname(p).expand_path }.each do |f|
129
+ kube_secret_file_validate!(f)
130
+ end)
131
+ end
132
+ end
133
+
134
+ def kube_chart_secret_values_path
135
+ kube_chart_path('secret-values.yaml').expand_path
136
+ end
137
+
6
138
  def kube_check_helm!
7
139
  raise Error::Command, code: :helm_not_found if shellout('which helm').exitstatus == 1
8
140
  end
@@ -4,97 +4,12 @@ module Dapp
4
4
  module Command
5
5
  module Deploy
6
6
  def kube_deploy
7
- raise Error::Command, code: :helm_directory_not_exist unless kube_chart_path.exist?
8
- kube_check_helm!
9
- kube_check_helm_chart!
10
-
11
- repo = option_repo
12
- image_version = options[:image_version]
13
- validate_repo_name!(repo)
14
- validate_tag_name!(image_version)
15
-
16
- # TODO: Перенести код процесса выката в Helm::Manager
17
-
18
- with_kube_tmp_chart_dir do
19
- kube_copy_chart
20
- kube_helm_decode_secrets
21
- kube_generate_helm_chart_tpl
22
-
23
- release = Helm::Release.new(
24
- self,
25
- name: kube_release_name,
26
- repo: repo,
27
- image_version: image_version,
28
- namespace: kube_namespace,
29
- chart_path: kube_chart_path_for_helm,
30
- set: self.options[:helm_set_options],
31
- values: [*kube_values_paths, *kube_tmp_chart_secret_values_paths],
32
- deploy_timeout: self.options[:timeout] || 300
33
- )
34
-
7
+ helm_release do |release|
35
8
  kube_flush_hooks_jobs(release)
36
9
  kube_run_deploy(release)
37
10
  end
38
11
  end
39
12
 
40
- def kube_copy_chart
41
- FileUtils.cp_r("#{kube_chart_path}/.", kube_chart_path_for_helm)
42
- end
43
-
44
- def kube_helm_decode_secrets
45
- if secret.nil?
46
- log_warning(desc: {
47
- code: :dapp_secret_key_not_found,
48
- data: {not_found_in: secret_key_not_found_in.join(', ')}
49
- }) if !kube_secret_values_paths.empty? || kube_chart_secret_path.directory?
50
- else
51
- kube_helm_decode_secret_files
52
- end
53
- kube_helm_decode_secret_values
54
- end
55
-
56
- def kube_helm_decode_secret_values
57
- kube_secret_values_paths.each_with_index do |secret_values_file, index|
58
- decoded_data = kube_helm_decode_json(secret, yaml_load_file(secret_values_file))
59
- kube_tmp_chart_secret_values_paths[index].write(decoded_data.to_yaml)
60
- end
61
- end
62
-
63
- def kube_helm_decode_secret_files
64
- return unless kube_chart_secret_path.directory?
65
- Dir.glob(kube_chart_secret_path.join('**/*')).each do |entry|
66
- next if File.directory?(entry)
67
- kube_secret_file_validate!(entry)
68
- secret_relative_path = Pathname(entry).subpath_of(kube_chart_secret_path)
69
- secret_data = secret.extract(IO.binread(entry).chomp("\n"))
70
- File.open(kube_tmp_chart_secret_path(secret_relative_path), 'wb:ASCII-8BIT', 0400) {|f| f.write secret_data}
71
- end
72
- end
73
-
74
- def kube_generate_helm_chart_tpl
75
- cont = <<-EOF
76
- {{/* vim: set filetype=mustache: */}}
77
-
78
- {{- define "dimg" -}}
79
- {{- if (ge (len (index .)) 2) -}}
80
- {{- $name := index . 0 -}}
81
- {{- $context := index . 1 -}}
82
- {{- printf "%v:%v-%v" $context.Values.global.dapp.repo $name $context.Values.global.dapp.image_version -}}
83
- {{- else -}}
84
- {{- $context := index . 0 -}}
85
- {{- printf "%v:%v" $context.Values.global.dapp.repo $context.Values.global.dapp.image_version -}}
86
- {{- end -}}
87
- {{- end -}}
88
-
89
- {{- define "dapp_secret_file" -}}
90
- {{- $relative_file_path := index . 0 -}}
91
- {{- $context := index . 1 -}}
92
- {{- $context.Files.Get (print "#{kube_tmp_chart_secret_path.subpath_of(kube_chart_path_for_helm)}/" $relative_file_path) -}}
93
- {{- end -}}
94
- EOF
95
- kube_chart_path_for_helm('templates/_dapp_helpers.tpl').write(cont)
96
- end
97
-
98
13
  def kube_flush_hooks_jobs(release)
99
14
  release.hooks.values
100
15
  .reject { |job| ['0', 'false'].include? job.annotations["dapp/recreate"].to_s }
@@ -167,41 +82,6 @@ module Dapp
167
82
  end
168
83
  end
169
84
  end
170
-
171
- def kube_check_helm_chart!
172
- raise Error::Command, code: :project_helm_chart_not_found, data: { path: kube_chart_path } unless kube_chart_path.exist?
173
- end
174
-
175
- def kube_tmp_chart_secret_path(*path)
176
- kube_chart_path_for_helm('decoded-secret', *path).tap { |p| p.parent.mkpath }
177
- end
178
-
179
- def kube_values_paths
180
- self.options[:helm_values_options].map { |p| Pathname(p).expand_path }.each do |f|
181
- raise Error::Command, code: :values_file_not_found, data: { path: f } unless f.file?
182
- end
183
- end
184
-
185
- def kube_tmp_chart_secret_values_paths
186
- @kube_tmp_chart_secret_values_paths ||= kube_secret_values_paths.each_with_index.map { |f, i| kube_chart_path_for_helm( "decoded-secret-values-#{i}.yaml") }
187
- end
188
-
189
- def kube_secret_values_paths
190
- @kube_chart_secret_values_files ||= [].tap do |files|
191
- files << kube_chart_secret_values_path if kube_chart_secret_values_path.file?
192
- files.concat(options[:helm_secret_values_options].map { |p| Pathname(p).expand_path }.each do |f|
193
- kube_secret_file_validate!(f)
194
- end)
195
- end
196
- end
197
-
198
- def kube_chart_secret_values_path
199
- kube_chart_path('secret-values.yaml').expand_path
200
- end
201
-
202
- def kube_helm_manager
203
- @kube_helm_manager ||= Helm::Manager.new(self)
204
- end
205
85
  end
206
86
  end
207
87
  end
@@ -0,0 +1,79 @@
1
+ module Dapp
2
+ module Kube
3
+ module Dapp
4
+ module Command
5
+ module Lint
6
+ def kube_chart_name
7
+ chart_yaml_path = kube_chart_path.join("Chart.yaml")
8
+ chart_spec = yaml_load_file(chart_yaml_path)
9
+
10
+ if chart_spec["name"].nil? || chart_spec["name"].empty?
11
+ raise Error::Command, code: :bad_helm_chart_spec_name, data: { name: chart_spec["name"], path: chart_yaml_path, raw_spec: chart_yaml_path.read.strip }
12
+ end
13
+
14
+ chart_spec["name"]
15
+ end
16
+
17
+ def with_kube_tmp_lint_chart_dir(&blk)
18
+ old_kube_tmp_helm_chart_dir = @kube_tmp_helm_chart_dir
19
+ unless ENV['DAPP_HELM_CHART_DIR']
20
+ @kube_tmp_helm_chart_dir = File.join(Dir.mktmpdir('dapp-helm-lint-', tmp_base_dir), kube_chart_name)
21
+ end
22
+
23
+ begin
24
+ with_kube_tmp_chart_dir(&blk)
25
+ ensure
26
+ @kube_tmp_helm_chart_dir = old_kube_tmp_helm_chart_dir
27
+ end
28
+ end
29
+
30
+ def kube_lint
31
+ kube_check_helm_chart!
32
+
33
+ repo = option_repo
34
+ image_version = options[:image_version]
35
+
36
+ with_kube_tmp_lint_chart_dir do
37
+ kube_copy_chart
38
+ kube_generate_helm_chart_tpl
39
+ kube_helm_decode_secrets
40
+
41
+ all_values = {}
42
+ [kube_chart_path('values.yaml').expand_path, *kube_values_paths, *kube_tmp_chart_secret_values_paths].each do |values_path|
43
+ all_values = all_values.in_depth_merge(yaml_load_file(values_path))
44
+ end
45
+
46
+ options[:helm_set_options].each do |opt_spec|
47
+ name, _, value = opt_spec.partition("=")
48
+ keys = name.split(".")
49
+
50
+ values = all_values
51
+ keys.each_with_index do |key, ind|
52
+ if ind == keys.size - 1
53
+ values[key] = YAML.load(value)
54
+ else
55
+ values[key] ||= {}
56
+ values = values[key]
57
+ end
58
+ end
59
+ end
60
+
61
+ all_values['global'] = {
62
+ 'namespace' => kube_namespace,
63
+ 'dapp' => {
64
+ 'repo' => option_repo,
65
+ 'image_version' => options[:image_version]
66
+ }
67
+ }
68
+
69
+ kube_chart_path_for_helm.join("values.yaml").write YAML.dump(all_values)
70
+
71
+ shellout! "helm lint --strict #{kube_chart_path_for_helm}"
72
+ end
73
+ end
74
+
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,13 @@
1
+ module Dapp
2
+ module Kube
3
+ module Dapp
4
+ module Command
5
+ module Render
6
+ def kube_render
7
+ helm_release { |release| release.templates.values.each { |t| puts t } }
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -13,6 +13,8 @@ module Dapp
13
13
  include Command::SecretEdit
14
14
  include Command::MinikubeSetup
15
15
  include Command::ChartCreate
16
+ include Command::Render
17
+ include Command::Lint
16
18
  include Command::Common
17
19
  end
18
20
  end
@@ -58,6 +58,29 @@ module Dapp
58
58
  dapp.shellout! "helm upgrade #{args.join(' ')}", verbose: true
59
59
  end
60
60
 
61
+ def templates
62
+ @templates ||= {}.tap do |t|
63
+ current_template = nil
64
+ spec = 0
65
+ evaluation_output.lines.each do |l|
66
+ if (match = l[/# Source: #{dapp.name}\/templates\/(.*)/, 1])
67
+ spec = 0
68
+ t[current_template = match] ||= []
69
+ end
70
+
71
+ if l[/^---$/]
72
+ spec += 1
73
+ elsif current_template
74
+ (t[current_template][spec] ||= []) << l
75
+ end
76
+ end
77
+
78
+ t.each do |template, specs|
79
+ t[template] = "---\n#{specs.map(&:join).join("---\n").strip}"
80
+ end
81
+ end
82
+ end
83
+
61
84
  protected
62
85
 
63
86
  def evaluation_output
@@ -94,10 +117,10 @@ module Dapp
94
117
 
95
118
  def set_options
96
119
  [].tap do |options|
120
+ options.concat(set.map { |opt| "--set #{opt}" })
97
121
  options << "--set global.dapp.repo=#{repo}"
98
122
  options << "--set global.dapp.image_version=#{image_version}"
99
123
  options << "--set global.namespace=#{namespace}"
100
- options.concat(set.map { |opt| "--set #{opt}" })
101
124
  end
102
125
  end
103
126
 
@@ -42,7 +42,7 @@ module Dapp
42
42
  sleep 0.1
43
43
  next
44
44
  rescue Kubernetes::Client::Error::Base => err
45
- dapp.log_warning("Error while fetching pod's #{pod_manager.name} logs: #{err.message}")
45
+ dapp.log_warning("#{dapp.log_time}Error while fetching pod's #{pod_manager.name} logs: #{err.message}", stream: dapp.service_stream)
46
46
  break
47
47
  end
48
48
 
@@ -132,7 +132,7 @@ module Dapp
132
132
  rescue Kubernetes::Client::Error::Pod::ContainerCreating, Kubernetes::Client::Error::Pod::PodInitializing
133
133
  next
134
134
  rescue Kubernetes::Client::Error::Base => err
135
- dapp.log_warning("Error while fetching pod's #{pod.name} logs: #{err.message}")
135
+ dapp.log_warning("#{dapp.log_time}Error while fetching pod's #{pod.name} logs: #{err.message}", stream: dapp.service_stream)
136
136
  next
137
137
  end
138
138
 
@@ -172,7 +172,7 @@ module Dapp
172
172
  end
173
173
  else
174
174
  dapp.with_log_indent do
175
- dapp.log_warning("Unknown pod readiness condition reason '#{ready_condition['reason']}': #{ready_condition}")
175
+ dapp.log_warning("#{dapp.log_time}Unknown pod readiness condition reason '#{ready_condition['reason']}': #{ready_condition}", stream: dapp.service_stream)
176
176
  end
177
177
  end
178
178
  end # with_log_indent
@@ -40,7 +40,7 @@ module Dapp
40
40
  if job.succeeded?
41
41
  break
42
42
  elsif job.failed?
43
- dapp.log_warning "Job '#{name}' has been failed: #{job.spec['status']}"
43
+ dapp.log_warning "#{dapp.log_time}Job '#{name}' has been failed: #{job.spec['status']}", stream: dapp.service_stream
44
44
  break
45
45
  end
46
46
 
@@ -53,7 +53,7 @@ module Dapp
53
53
  begin
54
54
  pod_manager.watch_till_done!
55
55
  rescue Kubernetes::Client::Error::Pod::NotFound => err
56
- dapp.log_warning "Pod '#{pod_manager.name}' has been deleted"
56
+ dapp.log_warning "#{dapp.log_time}Pod '#{pod_manager.name}' has been deleted", stream: dapp.service_stream
57
57
  ensure
58
58
  @processed_pods_names << process_pod.name
59
59
  end
data/lib/dapp/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Dapp
2
- VERSION = '0.18.2'.freeze
2
+ VERSION = '0.18.3'.freeze
3
3
  BUILD_CACHE_VERSION = 20
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.18.2
4
+ version: 0.18.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Stolyarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-07 00:00:00.000000000 Z
11
+ date: 2017-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-shellout
@@ -647,7 +647,9 @@ files:
647
647
  - lib/dapp/kube/cli/command/kube/chart_create.rb
648
648
  - lib/dapp/kube/cli/command/kube/deploy.rb
649
649
  - lib/dapp/kube/cli/command/kube/dismiss.rb
650
+ - lib/dapp/kube/cli/command/kube/lint.rb
650
651
  - lib/dapp/kube/cli/command/kube/minikube_setup.rb
652
+ - lib/dapp/kube/cli/command/kube/render.rb
651
653
  - lib/dapp/kube/cli/command/kube/secret_edit.rb
652
654
  - lib/dapp/kube/cli/command/kube/secret_extract.rb
653
655
  - lib/dapp/kube/cli/command/kube/secret_generate.rb
@@ -657,7 +659,9 @@ files:
657
659
  - lib/dapp/kube/dapp/command/common.rb
658
660
  - lib/dapp/kube/dapp/command/deploy.rb
659
661
  - lib/dapp/kube/dapp/command/dismiss.rb
662
+ - lib/dapp/kube/dapp/command/lint.rb
660
663
  - lib/dapp/kube/dapp/command/minikube_setup.rb
664
+ - lib/dapp/kube/dapp/command/render.rb
661
665
  - lib/dapp/kube/dapp/command/secret_edit.rb
662
666
  - lib/dapp/kube/dapp/command/secret_extract.rb
663
667
  - lib/dapp/kube/dapp/command/secret_generate.rb
@@ -706,7 +710,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
706
710
  version: 2.5.0
707
711
  requirements: []
708
712
  rubyforge_project:
709
- rubygems_version: 2.7.1
713
+ rubygems_version: 2.7.2
710
714
  signing_key:
711
715
  specification_version: 4
712
716
  summary: Build docker packaged apps using chef or shell