kubernetes-deploy 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.buildkite/pipeline.nightly.yml +8 -7
- data/CHANGELOG.md +20 -0
- data/dev.yml +1 -1
- data/kubernetes-deploy.gemspec +1 -1
- data/lib/kubernetes-deploy/deploy_task.rb +70 -41
- data/lib/kubernetes-deploy/errors.rb +9 -0
- data/lib/kubernetes-deploy/kubernetes_resource.rb +8 -4
- data/lib/kubernetes-deploy/kubernetes_resource/deployment.rb +15 -4
- data/lib/kubernetes-deploy/kubernetes_resource/pod.rb +4 -2
- data/lib/kubernetes-deploy/kubernetes_resource/replica_set.rb +4 -2
- data/lib/kubernetes-deploy/renderer.rb +17 -19
- data/lib/kubernetes-deploy/resource_watcher.rb +2 -2
- data/lib/kubernetes-deploy/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a581b73a9b59ce7dbc35a528acf269ba9ee12523
|
4
|
+
data.tar.gz: 4d3b6268317bf30b3011d1eb3e9f8bcc9c731c4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15197ca3f8d90b28927dc8a5ab365bb7f455434c49af708db82b2f8f5dd7430420a8e4819edbc1d4579cd2291df0a002f11924be3a865631a11e5a1fa3f3b344
|
7
|
+
data.tar.gz: bae4f408b4bfad19e61754991f24bf34d48dca2929f1d33dbd592b2fcc009b7135adc3dc92201c1e8d7633d80520a798e03aedec45778d59d81aa0a872ab7426
|
@@ -1,10 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
# Disableed until minikube can run 1.10
|
2
|
+
# - name: 'Run Test Suite (:kubernetes: 1.10-latest)'
|
3
|
+
# command: bin/ci
|
4
|
+
# agents:
|
5
|
+
# queue: minikube-ci
|
6
|
+
# env:
|
7
|
+
# LOGGING_LEVEL: 4
|
8
|
+
# KUBERNETES_VERSION: v1.10-latest
|
8
9
|
- name: 'Run Test Suite (:kubernetes: 1.9-latest)'
|
9
10
|
command: bin/ci
|
10
11
|
agents:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
### Master
|
2
|
+
|
3
|
+
*Features*
|
4
|
+
|
5
|
+
*Bug Fixes*
|
6
|
+
|
7
|
+
*Enhancements*
|
8
|
+
|
9
|
+
### 0.20.0
|
10
|
+
|
11
|
+
*Features*
|
12
|
+
- Automatically add all Kubernetes namespace labels to StatsD tags ([#278](https://github.com/Shopify/kubernetes-deploy/pull/278))
|
13
|
+
|
14
|
+
*Bug Fixes*
|
15
|
+
- Prevent calling sleep with a negative value ([#273](https://github.com/Shopify/kubernetes-deploy/pull/273))
|
16
|
+
- Prevent no-op redeploys of bad code from hanging forever ([#262](https://github.com/Shopify/kubernetes-deploy/pull/262))
|
17
|
+
|
18
|
+
*Enhancements*
|
19
|
+
- Improve output for rendering errors ([#253](https://github.com/Shopify/kubernetes-deploy/pull/253))
|
20
|
+
|
1
21
|
### 0.19.0
|
2
22
|
*Features*
|
3
23
|
- Added `--max-watch-seconds=seconds` to kubernetes-restart and kubernetes-deploy. When set
|
data/dev.yml
CHANGED
@@ -8,7 +8,7 @@ up:
|
|
8
8
|
- custom:
|
9
9
|
name: Minikube Cluster
|
10
10
|
met?: test $(minikube status | grep Running | wc -l) -eq 2 && $(minikube status | grep -q 'Correctly Configured')
|
11
|
-
meet: minikube start --
|
11
|
+
meet: minikube start --kubernetes-version=v1.9.4 --vm-driver=hyperkit
|
12
12
|
down: minikube stop
|
13
13
|
commands:
|
14
14
|
reset-minikube: minikube delete && rm -rf ~/.minikube
|
data/kubernetes-deploy.gemspec
CHANGED
@@ -36,5 +36,5 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency "minitest", "~> 5.0"
|
37
37
|
spec.add_development_dependency "minitest-stub-const", "~> 0.6"
|
38
38
|
spec.add_development_dependency "webmock", "~> 3.0"
|
39
|
-
spec.add_development_dependency "mocha", "~> 1.
|
39
|
+
spec.add_development_dependency "mocha", "~> 1.5"
|
40
40
|
end
|
@@ -92,6 +92,7 @@ module KubernetesDeploy
|
|
92
92
|
def initialize(namespace:, context:, current_sha:, template_dir:, logger:, kubectl_instance: nil, bindings: {},
|
93
93
|
max_watch_seconds: nil)
|
94
94
|
@namespace = namespace
|
95
|
+
@namespace_tags = []
|
95
96
|
@context = context
|
96
97
|
@current_sha = current_sha
|
97
98
|
@template_dir = File.expand_path(template_dir)
|
@@ -122,6 +123,7 @@ module KubernetesDeploy
|
|
122
123
|
validate_configuration(allow_protected_ns: allow_protected_ns, prune: prune)
|
123
124
|
confirm_context_exists
|
124
125
|
confirm_namespace_exists
|
126
|
+
@namespace_tags |= tags_from_namespace_labels
|
125
127
|
resources = discover_resources
|
126
128
|
validate_definitions(resources)
|
127
129
|
|
@@ -187,15 +189,6 @@ module KubernetesDeploy
|
|
187
189
|
|
188
190
|
private
|
189
191
|
|
190
|
-
# Inspect the file referenced in the kubectl stderr
|
191
|
-
# to make it easier for developer to understand what's going on
|
192
|
-
def find_bad_files_from_kubectl_output(stderr)
|
193
|
-
# stderr often contains one or more lines like the following, from which we can extract the file path(s):
|
194
|
-
# Error from server (TypeOfError): error when creating "/path/to/service-gqq5oh.yml": Service "web" is invalid:
|
195
|
-
matches = stderr.scan(%r{"(/\S+\.ya?ml\S*)"})
|
196
|
-
matches&.flatten
|
197
|
-
end
|
198
|
-
|
199
192
|
def deploy_has_priority_resources?(resources)
|
200
193
|
resources.any? { |r| PREDEPLOY_SEQUENCE.include?(r.type) }
|
201
194
|
end
|
@@ -225,7 +218,8 @@ module KubernetesDeploy
|
|
225
218
|
return unless failed_resources.present?
|
226
219
|
|
227
220
|
failed_resources.each do |r|
|
228
|
-
|
221
|
+
content = File.read(r.file_path) if File.file?(r.file_path)
|
222
|
+
record_invalid_template(err: r.validation_error_msg, filename: File.basename(r.file_path), content: content)
|
229
223
|
end
|
230
224
|
raise FatalDeploymentError, "Template validation failed"
|
231
225
|
end
|
@@ -238,7 +232,8 @@ module KubernetesDeploy
|
|
238
232
|
next unless filename.end_with?(".yml.erb", ".yml", ".yaml", ".yaml.erb")
|
239
233
|
|
240
234
|
split_templates(filename) do |r_def|
|
241
|
-
r = KubernetesResource.build(namespace: @namespace, context: @context, logger: @logger,
|
235
|
+
r = KubernetesResource.build(namespace: @namespace, context: @context, logger: @logger,
|
236
|
+
definition: r_def, statsd_tags: @namespace_tags)
|
242
237
|
resources << r
|
243
238
|
@logger.info " - #{r.id}"
|
244
239
|
end
|
@@ -250,34 +245,25 @@ module KubernetesDeploy
|
|
250
245
|
file_content = File.read(File.join(@template_dir, filename))
|
251
246
|
rendered_content = @renderer.render_template(filename, file_content)
|
252
247
|
YAML.load_stream(rendered_content) do |doc|
|
253
|
-
|
248
|
+
next if doc.blank?
|
249
|
+
unless doc.is_a?(Hash)
|
250
|
+
raise InvalidTemplateError.new("Template is not a valid Kubernetes manifest",
|
251
|
+
filename: filename, content: doc)
|
252
|
+
end
|
253
|
+
yield doc
|
254
254
|
end
|
255
|
+
rescue InvalidTemplateError => e
|
256
|
+
record_invalid_template(err: e.message, filename: e.filename, content: e.content)
|
257
|
+
raise FatalDeploymentError, "Failed to render and parse template"
|
255
258
|
rescue Psych::SyntaxError => e
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
Template content:
|
260
|
-
---
|
261
|
-
INFO
|
262
|
-
debug_msg += rendered_content
|
263
|
-
@logger.summary.add_paragraph(debug_msg)
|
264
|
-
raise FatalDeploymentError, "Template '#{filename}' cannot be parsed"
|
259
|
+
record_invalid_template(err: e.message, filename: filename, content: rendered_content)
|
260
|
+
raise FatalDeploymentError, "Failed to render and parse template"
|
265
261
|
end
|
266
262
|
|
267
|
-
def record_invalid_template(err
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
contents << File.read(file_path)
|
272
|
-
template_names << File.basename(file_path) unless original_filenames
|
273
|
-
end.join("\n")
|
274
|
-
template_list = template_names.compact.join(", ").presence || "See error message"
|
275
|
-
|
276
|
-
debug_msg = ColorizedString.new("Invalid #{'template'.pluralize(template_names.length)}: #{template_list}\n").red
|
277
|
-
debug_msg += "> Error from kubectl:\n#{indent_four(err)}"
|
278
|
-
if file_content.present?
|
279
|
-
debug_msg += "\n> Rendered template content:\n#{indent_four(file_content)}"
|
280
|
-
end
|
263
|
+
def record_invalid_template(err:, filename:, content:)
|
264
|
+
debug_msg = ColorizedString.new("Invalid template: #{filename}\n").red
|
265
|
+
debug_msg += "> Error message:\n#{indent_four(err)}"
|
266
|
+
debug_msg += "\n> Template content:\n#{indent_four(content)}"
|
281
267
|
@logger.summary.add_paragraph(debug_msg)
|
282
268
|
end
|
283
269
|
|
@@ -406,11 +392,7 @@ module KubernetesDeploy
|
|
406
392
|
if st.success?
|
407
393
|
log_pruning(out) if prune
|
408
394
|
else
|
409
|
-
|
410
|
-
warn_msg = "WARNING: Any resources not mentioned in the error below were likely created/updated. " \
|
411
|
-
"You may wish to roll back this deploy."
|
412
|
-
@logger.summary.add_paragraph(ColorizedString.new(warn_msg).yellow)
|
413
|
-
record_invalid_template(err, file_paths: file_paths)
|
395
|
+
record_apply_failure(err)
|
414
396
|
raise FatalDeploymentError, "Command failed: #{Shellwords.join(command)}"
|
415
397
|
end
|
416
398
|
end
|
@@ -424,6 +406,41 @@ module KubernetesDeploy
|
|
424
406
|
@logger.summary.add_action("pruned #{pruned.length} #{'resource'.pluralize(pruned.length)}")
|
425
407
|
end
|
426
408
|
|
409
|
+
def record_apply_failure(err)
|
410
|
+
warn_msg = "WARNING: Any resources not mentioned in the error(s) below were likely created/updated. " \
|
411
|
+
"You may wish to roll back this deploy."
|
412
|
+
@logger.summary.add_paragraph(ColorizedString.new(warn_msg).yellow)
|
413
|
+
|
414
|
+
unidentified_errors = []
|
415
|
+
err.each_line do |line|
|
416
|
+
bad_files = find_bad_files_from_kubectl_output(line)
|
417
|
+
if bad_files.present?
|
418
|
+
bad_files.each { |f| record_invalid_template(err: f[:err], filename: f[:filename], content: f[:content]) }
|
419
|
+
else
|
420
|
+
unidentified_errors << line
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
if unidentified_errors.present?
|
425
|
+
msg = "#{ColorizedString.new('Unidentified error(s):').red}\n#{indent_four(unidentified_errors.join)}"
|
426
|
+
@logger.summary.add_paragraph(msg)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
# Inspect the file referenced in the kubectl stderr
|
431
|
+
# to make it easier for developer to understand what's going on
|
432
|
+
def find_bad_files_from_kubectl_output(line)
|
433
|
+
# stderr often contains one or more lines like the following, from which we can extract the file path(s):
|
434
|
+
# Error from server (TypeOfError): error when creating "/path/to/service-gqq5oh.yml": Service "web" is invalid:
|
435
|
+
|
436
|
+
line.scan(%r{"(/\S+\.ya?ml\S*)"}).each_with_object([]) do |matches, bad_files|
|
437
|
+
matches.each do |path|
|
438
|
+
content = File.read(path) if File.file?(path)
|
439
|
+
bad_files << { filename: File.basename(path), err: line, content: content }
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
427
444
|
def confirm_context_exists
|
428
445
|
out, err, st = kubectl.run("config", "get-contexts", "-o", "name",
|
429
446
|
use_namespace: false, use_context: false, log_failure: false)
|
@@ -462,12 +479,24 @@ module KubernetesDeploy
|
|
462
479
|
@logger.info("Namespace #{@namespace} found")
|
463
480
|
end
|
464
481
|
|
482
|
+
def tags_from_namespace_labels
|
483
|
+
namespace_info = nil
|
484
|
+
with_retries(2) do
|
485
|
+
namespace_info, _, st = kubectl.run("get", "namespace", @namespace, "-o", "json", use_namespace: false,
|
486
|
+
log_failure: true)
|
487
|
+
st.success?
|
488
|
+
end
|
489
|
+
return [] if namespace_info.blank?
|
490
|
+
namespace_labels = JSON.parse(namespace_info, symbolize_names: true).fetch(:metadata, {}).fetch(:labels, {})
|
491
|
+
namespace_labels.map { |key, value| "#{key}:#{value}" }
|
492
|
+
end
|
493
|
+
|
465
494
|
def kubectl
|
466
495
|
@kubectl ||= Kubectl.new(namespace: @namespace, context: @context, logger: @logger, log_failure_by_default: true)
|
467
496
|
end
|
468
497
|
|
469
498
|
def statsd_tags
|
470
|
-
%W(namespace:#{@namespace} sha:#{@current_sha} context:#{@context})
|
499
|
+
%W(namespace:#{@namespace} sha:#{@current_sha} context:#{@context}) | @namespace_tags
|
471
500
|
end
|
472
501
|
|
473
502
|
def with_retries(limit)
|
@@ -3,6 +3,15 @@ module KubernetesDeploy
|
|
3
3
|
class FatalDeploymentError < StandardError; end
|
4
4
|
class KubectlError < StandardError; end
|
5
5
|
|
6
|
+
class InvalidTemplateError < FatalDeploymentError
|
7
|
+
attr_reader :filename, :content
|
8
|
+
def initialize(err, filename:, content: nil)
|
9
|
+
@filename = filename
|
10
|
+
@content = content
|
11
|
+
super(err)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
class NamespaceNotFoundError < FatalDeploymentError
|
7
16
|
def initialize(name, context)
|
8
17
|
super("Namespace `#{name}` not found in context `#{context}`")
|
@@ -28,8 +28,9 @@ module KubernetesDeploy
|
|
28
28
|
TIMEOUT_OVERRIDE_ANNOTATION = "kubernetes-deploy.shopify.io/timeout-override"
|
29
29
|
|
30
30
|
class << self
|
31
|
-
def build(namespace:, context:, definition:, logger:)
|
32
|
-
opts = { namespace: namespace, context: context, definition: definition, logger: logger
|
31
|
+
def build(namespace:, context:, definition:, logger:, statsd_tags:)
|
32
|
+
opts = { namespace: namespace, context: context, definition: definition, logger: logger,
|
33
|
+
statsd_tags: statsd_tags }
|
33
34
|
if KubernetesDeploy.const_defined?(definition["kind"])
|
34
35
|
klass = KubernetesDeploy.const_get(definition["kind"])
|
35
36
|
klass.new(**opts)
|
@@ -65,7 +66,7 @@ module KubernetesDeploy
|
|
65
66
|
"timeout: #{timeout}s"
|
66
67
|
end
|
67
68
|
|
68
|
-
def initialize(namespace:, context:, definition:, logger:)
|
69
|
+
def initialize(namespace:, context:, definition:, logger:, statsd_tags: [])
|
69
70
|
# subclasses must also set these if they define their own initializer
|
70
71
|
@name = definition.dig("metadata", "name")
|
71
72
|
unless @name.present?
|
@@ -73,6 +74,7 @@ module KubernetesDeploy
|
|
73
74
|
raise FatalDeploymentError, "Template is missing required field metadata.name"
|
74
75
|
end
|
75
76
|
|
77
|
+
@optional_statsd_tags = statsd_tags
|
76
78
|
@namespace = namespace
|
77
79
|
@context = context
|
78
80
|
@logger = logger
|
@@ -356,7 +358,9 @@ module KubernetesDeploy
|
|
356
358
|
else
|
357
359
|
"unknown"
|
358
360
|
end
|
359
|
-
%W(context:#{context} namespace:#{namespace} resource:#{id}
|
361
|
+
tags = %W(context:#{context} namespace:#{namespace} resource:#{id}
|
362
|
+
type:#{type} sha:#{ENV['REVISION']} status:#{status})
|
363
|
+
tags | @optional_statsd_tags
|
360
364
|
end
|
361
365
|
end
|
362
366
|
end
|
@@ -96,6 +96,16 @@ module KubernetesDeploy
|
|
96
96
|
|
97
97
|
private
|
98
98
|
|
99
|
+
def current_generation
|
100
|
+
return -2 unless exists? # different default than observed
|
101
|
+
@instance_data.dig('metadata', 'generation')
|
102
|
+
end
|
103
|
+
|
104
|
+
def observed_generation
|
105
|
+
return -1 unless exists? # different default than current
|
106
|
+
@instance_data.dig('status', 'observedGeneration')
|
107
|
+
end
|
108
|
+
|
99
109
|
def desired_replicas
|
100
110
|
return -1 unless exists?
|
101
111
|
@instance_data["spec"]["replicas"].to_i
|
@@ -133,12 +143,13 @@ module KubernetesDeploy
|
|
133
143
|
# Deployments were being updated prematurely with incorrect progress information
|
134
144
|
# https://github.com/kubernetes/kubernetes/issues/49637
|
135
145
|
return false unless Time.now.utc - @deploy_started_at >= progress_deadline.to_i
|
136
|
-
else
|
137
|
-
return false unless deploy_started?
|
138
146
|
end
|
139
147
|
|
140
|
-
|
141
|
-
|
148
|
+
# This assumes that when the controller bumps the observed generation, it also updates/clears all the status
|
149
|
+
# conditions. Specifically, it assumes the progress condition is immediately set to True if a rollout is starting.
|
150
|
+
deploy_started? &&
|
151
|
+
current_generation == observed_generation &&
|
152
|
+
progress_condition["status"] == 'False'
|
142
153
|
end
|
143
154
|
|
144
155
|
def find_latest_rs(mediator)
|
@@ -5,7 +5,8 @@ module KubernetesDeploy
|
|
5
5
|
|
6
6
|
FAILED_PHASE_NAME = "Failed"
|
7
7
|
|
8
|
-
def initialize(namespace:, context:, definition:, logger:,
|
8
|
+
def initialize(namespace:, context:, definition:, logger:,
|
9
|
+
statsd_tags: nil, parent: nil, deploy_started_at: nil)
|
9
10
|
@parent = parent
|
10
11
|
@deploy_started_at = deploy_started_at
|
11
12
|
@containers = definition.fetch("spec", {}).fetch("containers", []).map { |c| Container.new(c) }
|
@@ -14,7 +15,8 @@ module KubernetesDeploy
|
|
14
15
|
raise FatalDeploymentError, "Template is missing required field spec.containers"
|
15
16
|
end
|
16
17
|
@containers += definition["spec"].fetch("initContainers", []).map { |c| Container.new(c, init_container: true) }
|
17
|
-
super(namespace: namespace, context: context, definition: definition,
|
18
|
+
super(namespace: namespace, context: context, definition: definition,
|
19
|
+
logger: logger, statsd_tags: statsd_tags)
|
18
20
|
end
|
19
21
|
|
20
22
|
def sync(mediator)
|
@@ -5,11 +5,13 @@ module KubernetesDeploy
|
|
5
5
|
TIMEOUT = 5.minutes
|
6
6
|
attr_reader :pods
|
7
7
|
|
8
|
-
def initialize(namespace:, context:, definition:, logger:,
|
8
|
+
def initialize(namespace:, context:, definition:, logger:, statsd_tags: nil,
|
9
|
+
parent: nil, deploy_started_at: nil)
|
9
10
|
@parent = parent
|
10
11
|
@deploy_started_at = deploy_started_at
|
11
12
|
@pods = []
|
12
|
-
super(namespace: namespace, context: context, definition: definition,
|
13
|
+
super(namespace: namespace, context: context, definition: definition,
|
14
|
+
logger: logger, statsd_tags: statsd_tags)
|
13
15
|
end
|
14
16
|
|
15
17
|
SYNC_DEPENDENCIES = %w(Pod)
|
@@ -7,14 +7,14 @@ require 'json'
|
|
7
7
|
|
8
8
|
module KubernetesDeploy
|
9
9
|
class Renderer
|
10
|
-
class InvalidPartialError <
|
11
|
-
|
12
|
-
def initialize(msg, parents
|
10
|
+
class InvalidPartialError < InvalidTemplateError
|
11
|
+
attr_accessor :parents, :content, :filename
|
12
|
+
def initialize(msg, parents: [], content: nil, filename:)
|
13
13
|
@parents = parents
|
14
|
-
super(msg)
|
14
|
+
super(msg, content: content, filename: filename)
|
15
15
|
end
|
16
16
|
end
|
17
|
-
class PartialNotFound <
|
17
|
+
class PartialNotFound < InvalidTemplateError; end
|
18
18
|
|
19
19
|
def initialize(current_sha:, template_dir:, logger:, bindings: {})
|
20
20
|
@current_sha = current_sha
|
@@ -35,11 +35,11 @@ module KubernetesDeploy
|
|
35
35
|
|
36
36
|
ERB.new(raw_template, nil, '-').result(erb_binding)
|
37
37
|
rescue InvalidPartialError => err
|
38
|
-
|
39
|
-
|
38
|
+
err.parents = err.parents.dup.unshift(filename)
|
39
|
+
err.filename = "#{err.filename} (partial included from: #{err.parents.join(' -> ')})"
|
40
|
+
raise err
|
40
41
|
rescue StandardError => err
|
41
|
-
|
42
|
-
raise FatalDeploymentError, "Template '#{filename}' cannot be rendered"
|
42
|
+
raise InvalidTemplateError.new(err.message, filename: filename, content: raw_template)
|
43
43
|
end
|
44
44
|
|
45
45
|
def render_partial(partial, locals)
|
@@ -60,12 +60,14 @@ module KubernetesDeploy
|
|
60
60
|
# Note that JSON is a subset of YAML.
|
61
61
|
JSON.generate(docs.children.first.to_ruby)
|
62
62
|
rescue PartialNotFound => err
|
63
|
-
|
63
|
+
# get the filename from the first parent, not the missing partial itself
|
64
|
+
raise err if err.filename == partial
|
65
|
+
raise InvalidPartialError.new(err.message, filename: partial, content: expanded_template || template)
|
64
66
|
rescue InvalidPartialError => err
|
65
|
-
|
67
|
+
err.parents = err.parents.dup.unshift(File.basename(partial_path))
|
68
|
+
raise err
|
66
69
|
rescue StandardError => err
|
67
|
-
|
68
|
-
raise InvalidPartialError, "Template '#{partial_path}' cannot be rendered"
|
70
|
+
raise InvalidPartialError.new(err.message, filename: partial_path, content: expanded_template || template)
|
69
71
|
end
|
70
72
|
|
71
73
|
private
|
@@ -91,12 +93,8 @@ module KubernetesDeploy
|
|
91
93
|
return partial_path if File.exist?(partial_path)
|
92
94
|
end
|
93
95
|
end
|
94
|
-
raise PartialNotFound
|
95
|
-
|
96
|
-
|
97
|
-
def report_template_invalid(message, content)
|
98
|
-
@logger.summary.add_paragraph("Error from renderer:\n #{message.tr("\n", ' ')}")
|
99
|
-
@logger.summary.add_paragraph("Rendered template content:\n#{content}")
|
96
|
+
raise PartialNotFound.new("Could not find partial '#{name}' in any of #{@partials_dirs.join(':')}",
|
97
|
+
filename: name)
|
100
98
|
end
|
101
99
|
|
102
100
|
class TemplateContext
|
@@ -24,8 +24,8 @@ module KubernetesDeploy
|
|
24
24
|
if @timeout && (Time.now.utc - monitoring_started > @timeout)
|
25
25
|
report_and_give_up(remainder)
|
26
26
|
end
|
27
|
-
if Time.now.utc
|
28
|
-
sleep(
|
27
|
+
if (sleep_duration = delay_sync_until - Time.now.utc) > 0
|
28
|
+
sleep(sleep_duration)
|
29
29
|
end
|
30
30
|
delay_sync_until = Time.now.utc + delay_sync # don't pummel the API if the sync is fast
|
31
31
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kubernetes-deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katrina Verey
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-04-
|
12
|
+
date: 2018-04-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -185,14 +185,14 @@ dependencies:
|
|
185
185
|
requirements:
|
186
186
|
- - "~>"
|
187
187
|
- !ruby/object:Gem::Version
|
188
|
-
version: '1.
|
188
|
+
version: '1.5'
|
189
189
|
type: :development
|
190
190
|
prerelease: false
|
191
191
|
version_requirements: !ruby/object:Gem::Requirement
|
192
192
|
requirements:
|
193
193
|
- - "~>"
|
194
194
|
- !ruby/object:Gem::Version
|
195
|
-
version: '1.
|
195
|
+
version: '1.5'
|
196
196
|
description: Kubernetes deploy scripts
|
197
197
|
email:
|
198
198
|
- ops-accounts+shipit@shopify.com
|