dapp 0.18.2 → 0.18.3

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