krane 1.1.4 → 2.0.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/.rubocop-http---shopify-github-io-ruby-style-guide-rubocop-yml +8 -7
- data/.shopify-build/krane.yml +6 -6
- data/CHANGELOG.md +15 -0
- data/CONTRIBUTING.md +1 -1
- data/krane.gemspec +1 -1
- data/lib/krane/annotation.rb +11 -0
- data/lib/krane/cluster_resource_discovery.rb +2 -1
- data/lib/krane/concerns/template_reporting.rb +0 -6
- data/lib/krane/deploy_task.rb +13 -9
- data/lib/krane/ejson_secret_provisioner.rb +1 -2
- data/lib/krane/global_deploy_task.rb +2 -5
- data/lib/krane/kubernetes_resource.rb +13 -40
- data/lib/krane/kubernetes_resource/custom_resource.rb +1 -1
- data/lib/krane/kubernetes_resource/custom_resource_definition.rb +12 -9
- data/lib/krane/kubernetes_resource/deployment.rb +3 -5
- data/lib/krane/psych_k8s_compatibility.rb +36 -0
- data/lib/krane/renderer.rb +2 -0
- data/lib/krane/resource_deployer.rb +7 -2
- data/lib/krane/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57338bf07bebe1b05ce6701e0c89f2c91db5bd083818b35bd9f307aa669de5ba
|
4
|
+
data.tar.gz: 94850854c314bb1f05bbc43baa2759dc10e53ee9845c8f3d9b0d33e1a2d7dfd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0414c56878acd433ef3fabf36dd71920ab887adef61ce6b88c3a9dd298fedfb98c8cea39f0a2dfee1d789144ee3b175274e5ecccfd9ff08aad97322cc709463
|
7
|
+
data.tar.gz: 4f12d3be973fafb33dbbeb5f1f036afc6aa0cd5013b28a063c957befe34a0b65247e1a6b2390de49b52f5f6a9285de2206d5bbda819549a1a82e70e426c61a39
|
@@ -577,6 +577,7 @@ Layout/BlockEndNewline:
|
|
577
577
|
|
578
578
|
Style/CaseEquality:
|
579
579
|
Enabled: true
|
580
|
+
AllowOnConstant: true
|
580
581
|
|
581
582
|
Style/CharacterLiteral:
|
582
583
|
Enabled: true
|
@@ -659,6 +660,9 @@ Style/IfWithSemicolon:
|
|
659
660
|
Style/IdenticalConditionalBranches:
|
660
661
|
Enabled: true
|
661
662
|
|
663
|
+
Layout/IndentationStyle:
|
664
|
+
Enabled: true
|
665
|
+
|
662
666
|
Style/InfiniteLoop:
|
663
667
|
Enabled: true
|
664
668
|
|
@@ -803,9 +807,6 @@ Layout/SpaceInsideRangeLiteral:
|
|
803
807
|
Style/SymbolLiteral:
|
804
808
|
Enabled: true
|
805
809
|
|
806
|
-
Layout/Tab:
|
807
|
-
Enabled: true
|
808
|
-
|
809
810
|
Layout/TrailingWhitespace:
|
810
811
|
Enabled: true
|
811
812
|
|
@@ -834,7 +835,7 @@ Style/ZeroLengthPredicate:
|
|
834
835
|
Enabled: true
|
835
836
|
|
836
837
|
Layout/HeredocIndentation:
|
837
|
-
|
838
|
+
Enabled: true
|
838
839
|
|
839
840
|
Lint/AmbiguousOperator:
|
840
841
|
Enabled: true
|
@@ -872,9 +873,6 @@ Lint/EmptyEnsure:
|
|
872
873
|
Lint/EmptyInterpolation:
|
873
874
|
Enabled: true
|
874
875
|
|
875
|
-
Lint/EndInMethod:
|
876
|
-
Enabled: true
|
877
|
-
|
878
876
|
Lint/EnsureReturn:
|
879
877
|
Enabled: true
|
880
878
|
|
@@ -1018,3 +1016,6 @@ Style/ModuleFunction:
|
|
1018
1016
|
|
1019
1017
|
Lint/OrderedMagicComments:
|
1020
1018
|
Enabled: true
|
1019
|
+
|
1020
|
+
Lint/DeprecatedOpenSSLConstant:
|
1021
|
+
Enabled: true
|
data/.shopify-build/krane.yml
CHANGED
@@ -6,16 +6,15 @@ steps:
|
|
6
6
|
- label: Lint
|
7
7
|
timeout: 5m
|
8
8
|
run:
|
9
|
+
- bundle: ~
|
9
10
|
- bundle exec rubocop
|
10
|
-
|
11
|
-
- bundler
|
12
|
-
- label: 'Run Test Suite (:kubernetes: 1.17-latest :ruby: 2.7)'
|
11
|
+
- label: 'Run Test Suite (:kubernetes: 1.18-latest :ruby: 2.7)'
|
13
12
|
command: bin/ci
|
14
13
|
agents:
|
15
14
|
queue: k8s-ci
|
16
15
|
env:
|
17
16
|
LOGGING_LEVEL: "4"
|
18
|
-
KUBERNETES_VERSION: v1.
|
17
|
+
KUBERNETES_VERSION: v1.18-latest
|
19
18
|
RUBY_VERSION: "2.7"
|
20
19
|
- label: 'Run Test Suite (:kubernetes: 1.17-latest)'
|
21
20
|
command: bin/ci
|
@@ -24,13 +23,14 @@ steps:
|
|
24
23
|
env:
|
25
24
|
LOGGING_LEVEL: "4"
|
26
25
|
KUBERNETES_VERSION: v1.17-latest
|
27
|
-
- label: 'Run Test Suite (:kubernetes: 1.16
|
26
|
+
- label: 'Run Test Suite (:kubernetes: 1.16.12)'
|
28
27
|
command: bin/ci
|
29
28
|
agents:
|
30
29
|
queue: k8s-ci
|
31
30
|
env:
|
32
31
|
LOGGING_LEVEL: "4"
|
33
|
-
|
32
|
+
# Flip this back to v1.16-latest when 1.16.14 comes out (see #733)
|
33
|
+
KUBERNETES_VERSION: v1.16.12
|
34
34
|
- label: 'Run Test Suite (:kubernetes: 1.15-latest)'
|
35
35
|
command: bin/ci
|
36
36
|
agents:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## next
|
2
2
|
|
3
|
+
## 2.0.0
|
4
|
+
|
5
|
+
*Breaking Changes*
|
6
|
+
- Remove kubernetes deploy annotation prefix [#738](https://github.com/Shopify/krane/pull/738)
|
7
|
+
|
8
|
+
*Bug Fixes*
|
9
|
+
- Always set a deployment_id, even if the current_sha isn't set [#730](https://github.com/Shopify/krane/pull/730)
|
10
|
+
- YAML string scalars with scientific/e-notation numeric format not properly quoted. [#740](https://github.com/Shopify/krane/pull/740)
|
11
|
+
|
3
12
|
## 1.1.4
|
4
13
|
|
5
14
|
*Bug Fixes*
|
@@ -59,6 +68,12 @@
|
|
59
68
|
We've renamed the gem and cli to Krane.
|
60
69
|
See our [migration guide](https://github.com/Shopify/krane/blob/master/1.0-Upgrade.md) to help navigate the breaking changes.
|
61
70
|
|
71
|
+
## 1.0.0.pre.2
|
72
|
+
|
73
|
+
*Enhancements*
|
74
|
+
- Relax thor version requirement. ([#731](https://github.com/Shopify/krane/pull/731))
|
75
|
+
- Relax googleauth restriction. ([#731](https://github.com/Shopify/krane/pull/731))
|
76
|
+
|
62
77
|
## 1.0.0.pre.1
|
63
78
|
|
64
79
|
*Important!*
|
data/CONTRIBUTING.md
CHANGED
@@ -151,7 +151,7 @@ To see the full-color output of a specific integration test, you can use `PRINT_
|
|
151
151
|
1. Make sure CHANGELOG.md includes all user-facing changes since the last release. Things like test changes or refactors do not need to be included.
|
152
152
|
1. Update the version number in `version.rb`.
|
153
153
|
1. Commit your changes with message "Version x.y.z" and open a PR.
|
154
|
-
1. After merging your PR, deploy via [Shipit](https://shipit.shopify.io/shopify/
|
154
|
+
1. After merging your PR, deploy via [Shipit](https://shipit.shopify.io/shopify/krane/rubygems). Shipit will automatically tag the release and upload the gem to [rubygems.org](https://rubygems.org/gems/krane).
|
155
155
|
|
156
156
|
## CI (External contributors)
|
157
157
|
|
data/krane.gemspec
CHANGED
@@ -56,6 +56,6 @@ Gem::Specification.new do |spec|
|
|
56
56
|
spec.add_development_dependency("byebug")
|
57
57
|
spec.add_development_dependency("ruby-prof")
|
58
58
|
spec.add_development_dependency("ruby-prof-flamegraph")
|
59
|
-
spec.add_development_dependency("rubocop", "~> 0.
|
59
|
+
spec.add_development_dependency("rubocop", "~> 0.88.0")
|
60
60
|
spec.add_development_dependency("codecov")
|
61
61
|
end
|
@@ -88,7 +88,8 @@ module Krane
|
|
88
88
|
# Override list for kinds that don't appear in the lastest version of a group
|
89
89
|
version_override = { "CronJob" => "v1beta1", "VolumeAttachment" => "v1beta1",
|
90
90
|
"CSIDriver" => "v1beta1", "Ingress" => "v1beta1",
|
91
|
-
"CSINode" => "v1beta1", "Job" => "v1"
|
91
|
+
"CSINode" => "v1beta1", "Job" => "v1",
|
92
|
+
"IngressClass" => "v1beta1" }
|
92
93
|
|
93
94
|
pattern = /v(?<major>\d+)(?<pre>alpha|beta)?(?<minor>\d+)?/
|
94
95
|
latest = versions.sort_by do |version|
|
@@ -15,12 +15,6 @@ module Krane
|
|
15
15
|
logger.summary.add_paragraph(debug_msg)
|
16
16
|
end
|
17
17
|
|
18
|
-
def record_warnings(logger:, warning:, filename:)
|
19
|
-
warn_msg = "Template warning: #{filename}\n"
|
20
|
-
warn_msg += "> Warning message:\n#{Krane::FormattedLogger.indent_four(warning)}"
|
21
|
-
logger.summary.add_paragraph(ColorizedString.new(warn_msg).yellow)
|
22
|
-
end
|
23
|
-
|
24
18
|
def add_para_from_list(logger:, action:, enum:)
|
25
19
|
logger.summary.add_action(action)
|
26
20
|
logger.summary.add_paragraph(enum.map { |e| "- #{e}" }.join("\n"))
|
data/lib/krane/deploy_task.rb
CHANGED
@@ -4,6 +4,7 @@ require 'shellwords'
|
|
4
4
|
require 'tempfile'
|
5
5
|
require 'fileutils'
|
6
6
|
|
7
|
+
require 'krane/annotation'
|
7
8
|
require 'krane/common'
|
8
9
|
require 'krane/concurrency'
|
9
10
|
require 'krane/resource_cache'
|
@@ -56,6 +57,7 @@ module Krane
|
|
56
57
|
)
|
57
58
|
|
58
59
|
def predeploy_sequence
|
60
|
+
default_group = { group: nil }
|
59
61
|
before_crs = %w(
|
60
62
|
ResourceQuota
|
61
63
|
NetworkPolicy
|
@@ -65,12 +67,14 @@ module Krane
|
|
65
67
|
Role
|
66
68
|
RoleBinding
|
67
69
|
Secret
|
68
|
-
)
|
70
|
+
).map { |r| [r, default_group] }
|
71
|
+
|
69
72
|
after_crs = %w(
|
70
73
|
Pod
|
71
|
-
)
|
74
|
+
).map { |r| [r, default_group] }
|
72
75
|
|
73
|
-
|
76
|
+
crs = cluster_resource_discoverer.crds.select(&:predeployed?).map { |cr| [cr.kind, { group: cr.group }] }
|
77
|
+
Hash[before_crs + crs + after_crs]
|
74
78
|
end
|
75
79
|
|
76
80
|
def prune_whitelist
|
@@ -210,7 +214,10 @@ module Krane
|
|
210
214
|
end
|
211
215
|
|
212
216
|
def deploy_has_priority_resources?(resources)
|
213
|
-
resources.any?
|
217
|
+
resources.any? do |r|
|
218
|
+
next unless (pr = predeploy_sequence[r.type])
|
219
|
+
!pr[:group] || pr[:group] == r.group
|
220
|
+
end
|
214
221
|
end
|
215
222
|
|
216
223
|
def check_initial_status(resources)
|
@@ -242,6 +249,8 @@ module Krane
|
|
242
249
|
@logger.info(" - #{secret.id} (from ejson)")
|
243
250
|
end
|
244
251
|
|
252
|
+
StatsD.client.gauge('discover_resources.count', resources.size, tags: statsd_tags)
|
253
|
+
|
245
254
|
resources.sort
|
246
255
|
rescue InvalidTemplateError => e
|
247
256
|
record_invalid_template(logger: @logger, err: e.message, filename: e.filename,
|
@@ -274,11 +283,6 @@ module Krane
|
|
274
283
|
r.validate_definition(kubectl, selector: @selector)
|
275
284
|
end
|
276
285
|
|
277
|
-
resources.select(&:has_warnings?).each do |resource|
|
278
|
-
record_warnings(logger: @logger, warning: resource.validation_warning_msg,
|
279
|
-
filename: File.basename(resource.file_path))
|
280
|
-
end
|
281
|
-
|
282
286
|
failed_resources = resources.select(&:validation_failed?)
|
283
287
|
if failed_resources.present?
|
284
288
|
|
@@ -12,10 +12,10 @@ module Krane
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class EjsonSecretProvisioner
|
15
|
-
EJSON_SECRET_ANNOTATION = "kubernetes-deploy.shopify.io/ejson-secret"
|
16
15
|
EJSON_SECRET_KEY = "kubernetes_secrets"
|
17
16
|
EJSON_SECRETS_FILE = "secrets.ejson"
|
18
17
|
EJSON_KEYS_SECRET = "ejson-keys"
|
18
|
+
|
19
19
|
delegate :namespace, :context, :logger, to: :@task_config
|
20
20
|
|
21
21
|
def initialize(task_config:, ejson_keys_secret:, ejson_file:, statsd_tags:, selector: nil)
|
@@ -106,7 +106,6 @@ module Krane
|
|
106
106
|
"name" => secret_name,
|
107
107
|
"labels" => labels,
|
108
108
|
"namespace" => namespace,
|
109
|
-
"annotations" => { EJSON_SECRET_ANNOTATION => "true" },
|
110
109
|
},
|
111
110
|
"data" => encoded_data,
|
112
111
|
}
|
@@ -133,11 +133,6 @@ module Krane
|
|
133
133
|
r.validate_definition(@kubectl, selector: @selector)
|
134
134
|
end
|
135
135
|
|
136
|
-
resources.select(&:has_warnings?).each do |resource|
|
137
|
-
record_warnings(logger: logger, warning: resource.validation_warning_msg,
|
138
|
-
filename: File.basename(resource.file_path))
|
139
|
-
end
|
140
|
-
|
141
136
|
failed_resources = resources.select(&:validation_failed?)
|
142
137
|
if failed_resources.present?
|
143
138
|
failed_resources.each do |r|
|
@@ -173,6 +168,8 @@ module Krane
|
|
173
168
|
logger.info(" - #{r.id}")
|
174
169
|
end
|
175
170
|
|
171
|
+
StatsD.client.gauge('discover_resources.count', resources.size, tags: statsd_tags)
|
172
|
+
|
176
173
|
resources.sort
|
177
174
|
rescue InvalidTemplateError => e
|
178
175
|
record_invalid_template(logger: logger, err: e.message, filename: e.filename, content: e.content)
|
@@ -6,9 +6,12 @@ require 'krane/remote_logs'
|
|
6
6
|
require 'krane/duration_parser'
|
7
7
|
require 'krane/label_selector'
|
8
8
|
require 'krane/rollout_conditions'
|
9
|
+
require 'krane/psych_k8s_compatibility'
|
9
10
|
|
10
11
|
module Krane
|
11
12
|
class KubernetesResource
|
13
|
+
using PsychK8sCompatibility
|
14
|
+
|
12
15
|
attr_reader :name, :namespace, :context
|
13
16
|
attr_writer :type, :deploy_started_at, :global
|
14
17
|
|
@@ -32,9 +35,7 @@ module Krane
|
|
32
35
|
If you have reason to believe it will succeed, retry the deploy to continue to monitor the rollout.
|
33
36
|
MSG
|
34
37
|
|
35
|
-
|
36
|
-
TIMEOUT_OVERRIDE_ANNOTATION_DEPRECATED = "kubernetes-deploy.shopify.io/#{TIMEOUT_OVERRIDE_ANNOTATION_SUFFIX}"
|
37
|
-
TIMEOUT_OVERRIDE_ANNOTATION = "krane.shopify.io/#{TIMEOUT_OVERRIDE_ANNOTATION_SUFFIX}"
|
38
|
+
TIMEOUT_OVERRIDE_ANNOTATION = "timeout-override"
|
38
39
|
LAST_APPLIED_ANNOTATION = "kubectl.kubernetes.io/last-applied-configuration"
|
39
40
|
SENSITIVE_TEMPLATE_CONTENT = false
|
40
41
|
SERVER_DRY_RUNNABLE = false
|
@@ -103,7 +104,7 @@ module Krane
|
|
103
104
|
def timeout_override
|
104
105
|
return @timeout_override if defined?(@timeout_override)
|
105
106
|
|
106
|
-
@timeout_override = DurationParser.new(krane_annotation_value(
|
107
|
+
@timeout_override = DurationParser.new(krane_annotation_value(TIMEOUT_OVERRIDE_ANNOTATION)).parse!.to_i
|
107
108
|
rescue DurationParser::ParsingError
|
108
109
|
@timeout_override = nil
|
109
110
|
end
|
@@ -123,7 +124,6 @@ module Krane
|
|
123
124
|
@statsd_report_done = false
|
124
125
|
@disappeared = false
|
125
126
|
@validation_errors = []
|
126
|
-
@validation_warnings = []
|
127
127
|
@instance_data = {}
|
128
128
|
@server_dry_run_validated = false
|
129
129
|
end
|
@@ -134,22 +134,12 @@ module Krane
|
|
134
134
|
|
135
135
|
def validate_definition(kubectl, selector: nil)
|
136
136
|
@validation_errors = []
|
137
|
-
@validation_warnings = []
|
138
137
|
validate_selector(selector) if selector
|
139
138
|
validate_timeout_annotation
|
140
|
-
validate_annotation_version
|
141
139
|
validate_spec_with_kubectl(kubectl)
|
142
140
|
@validation_errors.present?
|
143
141
|
end
|
144
142
|
|
145
|
-
def validation_warning_msg
|
146
|
-
@validation_warnings.join("\n")
|
147
|
-
end
|
148
|
-
|
149
|
-
def has_warnings?
|
150
|
-
@validation_warnings.present?
|
151
|
-
end
|
152
|
-
|
153
143
|
def validation_error_msg
|
154
144
|
@validation_errors.join("\n")
|
155
145
|
end
|
@@ -228,6 +218,11 @@ module Krane
|
|
228
218
|
@type || self.class.kind
|
229
219
|
end
|
230
220
|
|
221
|
+
def group
|
222
|
+
grouping, version = @definition.dig("apiVersion").split("/")
|
223
|
+
version ? grouping : "core"
|
224
|
+
end
|
225
|
+
|
231
226
|
def kubectl_resource_type
|
232
227
|
type
|
233
228
|
end
|
@@ -495,8 +490,8 @@ module Krane
|
|
495
490
|
private
|
496
491
|
|
497
492
|
def validate_timeout_annotation
|
498
|
-
timeout_override_value = krane_annotation_value(
|
499
|
-
timeout_annotation_key =
|
493
|
+
timeout_override_value = krane_annotation_value(TIMEOUT_OVERRIDE_ANNOTATION)
|
494
|
+
timeout_annotation_key = Annotation.for(TIMEOUT_OVERRIDE_ANNOTATION)
|
500
495
|
return if timeout_override_value.nil?
|
501
496
|
|
502
497
|
override = DurationParser.new(timeout_override_value).parse!
|
@@ -509,30 +504,8 @@ module Krane
|
|
509
504
|
@validation_errors << "#{timeout_annotation_key} annotation is invalid: #{e}"
|
510
505
|
end
|
511
506
|
|
512
|
-
def validate_annotation_version
|
513
|
-
return if validation_warning_msg.include?("annotations is deprecated")
|
514
|
-
annotation_keys = @definition.dig("metadata", "annotations")&.keys
|
515
|
-
annotation_keys&.each do |annotation|
|
516
|
-
if annotation.include?("kubernetes-deploy.shopify.io")
|
517
|
-
annotation_prefix = annotation.split('/').first
|
518
|
-
@validation_warnings << "#{annotation_prefix} as a prefix for annotations is deprecated: "\
|
519
|
-
"Use the 'krane.shopify.io' annotation prefix instead"
|
520
|
-
return
|
521
|
-
end
|
522
|
-
end
|
523
|
-
end
|
524
|
-
|
525
507
|
def krane_annotation_value(suffix)
|
526
|
-
@definition.dig("metadata", "annotations",
|
527
|
-
@definition.dig("metadata", "annotations", "krane.shopify.io/#{suffix}")
|
528
|
-
end
|
529
|
-
|
530
|
-
def krane_annotation_key(suffix)
|
531
|
-
if @definition.dig("metadata", "annotations", "kubernetes-deploy.shopify.io/#{suffix}")
|
532
|
-
"kubernetes-deploy.shopify.io/#{suffix}"
|
533
|
-
elsif @definition.dig("metadata", "annotations", "krane.shopify.io/#{suffix}")
|
534
|
-
"krane.shopify.io/#{suffix}"
|
535
|
-
end
|
508
|
+
@definition.dig("metadata", "annotations", Annotation.for(suffix))
|
536
509
|
end
|
537
510
|
|
538
511
|
def validate_selector(selector)
|
@@ -70,7 +70,7 @@ module Krane
|
|
70
70
|
@validation_errors << "The CRD that specifies this resource is using invalid rollout conditions. " \
|
71
71
|
"Krane will not be able to continue until those rollout conditions are fixed.\n" \
|
72
72
|
"Rollout conditions can be found on the CRD that defines this resource (#{@crd.name}), " \
|
73
|
-
"under the annotation #{CustomResourceDefinition::ROLLOUT_CONDITIONS_ANNOTATION}.\n" \
|
73
|
+
"under the annotation #{Annotation.for(CustomResourceDefinition::ROLLOUT_CONDITIONS_ANNOTATION)}.\n" \
|
74
74
|
"Validation failed with: #{e}"
|
75
75
|
end
|
76
76
|
|
@@ -2,9 +2,8 @@
|
|
2
2
|
module Krane
|
3
3
|
class CustomResourceDefinition < KubernetesResource
|
4
4
|
TIMEOUT = 2.minutes
|
5
|
-
|
6
|
-
|
7
|
-
TIMEOUT_FOR_INSTANCE_ANNOTATION = "krane.shopify.io/instance-timeout"
|
5
|
+
ROLLOUT_CONDITIONS_ANNOTATION = "instance-rollout-conditions"
|
6
|
+
TIMEOUT_FOR_INSTANCE_ANNOTATION = "instance-timeout"
|
8
7
|
GLOBAL = true
|
9
8
|
|
10
9
|
def deploy_succeeded?
|
@@ -20,7 +19,7 @@ module Krane
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def timeout_for_instance
|
23
|
-
timeout = krane_annotation_value(
|
22
|
+
timeout = krane_annotation_value(TIMEOUT_FOR_INSTANCE_ANNOTATION)
|
24
23
|
DurationParser.new(timeout).parse!.to_i
|
25
24
|
rescue DurationParser::ParsingError
|
26
25
|
nil
|
@@ -46,6 +45,10 @@ module Krane
|
|
46
45
|
@definition.dig("spec", "names", "kind")
|
47
46
|
end
|
48
47
|
|
48
|
+
def group
|
49
|
+
@definition.dig("spec", "group")
|
50
|
+
end
|
51
|
+
|
49
52
|
def prunable?
|
50
53
|
prunable = krane_annotation_value("prunable")
|
51
54
|
prunable == "true"
|
@@ -59,8 +62,8 @@ module Krane
|
|
59
62
|
def rollout_conditions
|
60
63
|
return @rollout_conditions if defined?(@rollout_conditions)
|
61
64
|
|
62
|
-
@rollout_conditions = if krane_annotation_value(
|
63
|
-
RolloutConditions.from_annotation(krane_annotation_value(
|
65
|
+
@rollout_conditions = if krane_annotation_value(ROLLOUT_CONDITIONS_ANNOTATION)
|
66
|
+
RolloutConditions.from_annotation(krane_annotation_value(ROLLOUT_CONDITIONS_ANNOTATION))
|
64
67
|
end
|
65
68
|
rescue RolloutConditionsError
|
66
69
|
@rollout_conditions = nil
|
@@ -71,13 +74,13 @@ module Krane
|
|
71
74
|
|
72
75
|
validate_rollout_conditions
|
73
76
|
rescue RolloutConditionsError => e
|
74
|
-
@validation_errors << "Annotation #{
|
77
|
+
@validation_errors << "Annotation #{Annotation.for(ROLLOUT_CONDITIONS_ANNOTATION)} " \
|
75
78
|
"on #{name} is invalid: #{e}"
|
76
79
|
end
|
77
80
|
|
78
81
|
def validate_rollout_conditions
|
79
|
-
if krane_annotation_value(
|
80
|
-
conditions = RolloutConditions.from_annotation(krane_annotation_value(
|
82
|
+
if krane_annotation_value(ROLLOUT_CONDITIONS_ANNOTATION) && @rollout_conditions_validated.nil?
|
83
|
+
conditions = RolloutConditions.from_annotation(krane_annotation_value(ROLLOUT_CONDITIONS_ANNOTATION))
|
81
84
|
conditions.validate!
|
82
85
|
end
|
83
86
|
|
@@ -5,9 +5,7 @@ module Krane
|
|
5
5
|
class Deployment < KubernetesResource
|
6
6
|
TIMEOUT = 7.minutes
|
7
7
|
SYNC_DEPENDENCIES = %w(Pod ReplicaSet)
|
8
|
-
|
9
|
-
REQUIRED_ROLLOUT_ANNOTATION_DEPRECATED = "kubernetes-deploy.shopify.io/#{REQUIRED_ROLLOUT_ANNOTATION_SUFFIX}"
|
10
|
-
REQUIRED_ROLLOUT_ANNOTATION = "krane.shopify.io/#{REQUIRED_ROLLOUT_ANNOTATION_SUFFIX}"
|
8
|
+
REQUIRED_ROLLOUT_ANNOTATION = "required-rollout"
|
11
9
|
REQUIRED_ROLLOUT_TYPES = %w(maxUnavailable full none).freeze
|
12
10
|
DEFAULT_REQUIRED_ROLLOUT = 'full'
|
13
11
|
|
@@ -106,7 +104,7 @@ module Krane
|
|
106
104
|
|
107
105
|
strategy = @definition.dig('spec', 'strategy', 'type').to_s
|
108
106
|
if required_rollout.downcase == 'maxunavailable' && strategy.present? && strategy.downcase != 'rollingupdate'
|
109
|
-
@validation_errors << "'#{
|
107
|
+
@validation_errors << "'#{Annotation.for(REQUIRED_ROLLOUT_ANNOTATION)}: #{required_rollout}' " \
|
110
108
|
"is incompatible with strategy '#{strategy}'"
|
111
109
|
end
|
112
110
|
|
@@ -151,7 +149,7 @@ module Krane
|
|
151
149
|
end
|
152
150
|
|
153
151
|
def rollout_annotation_err_msg
|
154
|
-
"'#{
|
152
|
+
"'#{Annotation.for(REQUIRED_ROLLOUT_ANNOTATION)}: #{required_rollout}' is invalid. " \
|
155
153
|
"Acceptable values: #{REQUIRED_ROLLOUT_TYPES.join(', ')}"
|
156
154
|
end
|
157
155
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'psych'
|
4
|
+
|
5
|
+
module PsychK8sCompatibility
|
6
|
+
def self.massage_node(n)
|
7
|
+
if n.is_a?(Psych::Nodes::Scalar) &&
|
8
|
+
(n.style == Psych::Nodes::Scalar::PLAIN) &&
|
9
|
+
n.value.is_a?(String) &&
|
10
|
+
n.value =~ /\A[+-]?\d+(?:\.\d+)?[eE][+-]?\d+\z/
|
11
|
+
n.style = Psych::Nodes::Scalar::DOUBLE_QUOTED
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
refine Psych.singleton_class do
|
16
|
+
def dump(o, io = nil, options = {})
|
17
|
+
if io.is_a?(Hash)
|
18
|
+
options = io
|
19
|
+
io = nil
|
20
|
+
end
|
21
|
+
visitor = Psych::Visitors::YAMLTree.create(options)
|
22
|
+
visitor << o
|
23
|
+
visitor.tree.each { |n| PsychK8sCompatibility.massage_node(n) }
|
24
|
+
visitor.tree.yaml(io, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def dump_stream(*objects)
|
28
|
+
visitor = Psych::Visitors::YAMLTree.create({})
|
29
|
+
objects.each do |o|
|
30
|
+
visitor << o
|
31
|
+
end
|
32
|
+
visitor.tree.each { |n| PsychK8sCompatibility.massage_node(n) }
|
33
|
+
visitor.tree.yaml
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/krane/renderer.rb
CHANGED
@@ -46,8 +46,13 @@ module Krane
|
|
46
46
|
bare_pods.first.stream_logs = true
|
47
47
|
end
|
48
48
|
|
49
|
-
predeploy_sequence.each do |resource_type|
|
50
|
-
matching_resources = resource_list.select
|
49
|
+
predeploy_sequence.each do |resource_type, attributes|
|
50
|
+
matching_resources = resource_list.select do |r|
|
51
|
+
r.type == resource_type &&
|
52
|
+
(!attributes[:group] || r.group == attributes[:group])
|
53
|
+
end
|
54
|
+
StatsD.client.gauge('priority_resources.count', matching_resources.size, tags: statsd_tags)
|
55
|
+
|
51
56
|
next if matching_resources.empty?
|
52
57
|
deploy_resources(matching_resources, verify: true, record_summary: false)
|
53
58
|
|
data/lib/krane/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: krane
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katrina Verey
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-08-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -366,14 +366,14 @@ dependencies:
|
|
366
366
|
requirements:
|
367
367
|
- - "~>"
|
368
368
|
- !ruby/object:Gem::Version
|
369
|
-
version: 0.
|
369
|
+
version: 0.88.0
|
370
370
|
type: :development
|
371
371
|
prerelease: false
|
372
372
|
version_requirements: !ruby/object:Gem::Requirement
|
373
373
|
requirements:
|
374
374
|
- - "~>"
|
375
375
|
- !ruby/object:Gem::Version
|
376
|
-
version: 0.
|
376
|
+
version: 0.88.0
|
377
377
|
- !ruby/object:Gem::Dependency
|
378
378
|
name: codecov
|
379
379
|
requirement: !ruby/object:Gem::Requirement
|
@@ -423,6 +423,7 @@ files:
|
|
423
423
|
- exe/krane
|
424
424
|
- krane.gemspec
|
425
425
|
- lib/krane.rb
|
426
|
+
- lib/krane/annotation.rb
|
426
427
|
- lib/krane/bindings_parser.rb
|
427
428
|
- lib/krane/cli/deploy_command.rb
|
428
429
|
- lib/krane/cli/global_deploy_command.rb
|
@@ -476,6 +477,7 @@ files:
|
|
476
477
|
- lib/krane/label_selector.rb
|
477
478
|
- lib/krane/oj.rb
|
478
479
|
- lib/krane/options_helper.rb
|
480
|
+
- lib/krane/psych_k8s_compatibility.rb
|
479
481
|
- lib/krane/remote_logs.rb
|
480
482
|
- lib/krane/render_task.rb
|
481
483
|
- lib/krane/renderer.rb
|