krane 2.4.1 → 2.4.9

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: 93f7d9e842d616ea60e2c509f5e5a3fcb54d24375d426efd0345ba3a07dd2008
4
- data.tar.gz: 24ccdd3165654319b55632a866f85839268644cb32ee719f55f03de6e5f63eb6
3
+ metadata.gz: 19143bcc0bff115c5217d341827f0ff1d599598d86aa580fcbb73c53ddc035dd
4
+ data.tar.gz: 05fa737ceb0bf4150b27be5e9d80ad24e37fed4479805bc54dfbe93f0feff081
5
5
  SHA512:
6
- metadata.gz: 1c90430d28fe8513dd86aef6d160e04257beb66f294b998d780c66b27d8bdb7e5320947b06894399c49bcb336795f72a338fb197f3be4626467bfb286bbde2f0
7
- data.tar.gz: 98fc07319ed605978d558777cea947a187bf3857d229b95945096d446fdbacd2637102e34a9e03afb9f5472105ce39d5d396f9c1cf8bc6f4c0677f28e6b88e9b
6
+ metadata.gz: 1bb4fc65f921987387d8858b468fba3ed1f1f8fb00539e64ca75fa0c0cc817a87d87f9f59503feae19315d08ce54f0037b803a7c3638149cabc0eec46af99d94
7
+ data.tar.gz: 61efdb8c0a9a6ccfeee0414b0df447b64a4dabe5a88afcd10a630819c8b26629f14ac05f09eb11e5d68d48a8f4b2c899abbfe40e5effc78666a33907d2cc3304
@@ -12,6 +12,7 @@ jobs:
12
12
  matrix:
13
13
  ruby:
14
14
  # Use unique Ruby versions, or GitHub gets confused when building the rest of the matrix
15
+ - '3.1.2' # With k8s 1.23
15
16
  - '3.0.3' # With k8s 1.23
16
17
  - '3.0.2' # With k8s 1.22
17
18
  - '3.0.1' # With k8s 1.21
@@ -19,6 +20,10 @@ jobs:
19
20
  - '2.7' # With k8s 1.19
20
21
  include:
21
22
  # Match kind images with chosen version https://github.com/kubernetes-sigs/kind/releases
23
+ - ruby: '3.1.2'
24
+ kind_version: 'v0.11.1'
25
+ kubernetes_version: '1.23.0'
26
+ kind_image: 'kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac'
22
27
  - ruby: '3.0.3'
23
28
  kind_version: 'v0.11.1'
24
29
  kubernetes_version: '1.23.0'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  ## next
2
2
 
3
+ ## 2.4.9
4
+
5
+ - Fixed a Ruby 3.1 regression that caused an exception when using a `--bindings=@<file>` argument to `krane render` [#900](https://github.com/Shopify/krane/pull/900)
6
+
7
+ ## 2.4.8
8
+
9
+ - update googleauth gem version to 1.2
10
+ - add the `ruby-lsp` gem to development group in the Gemfile
11
+ ## 2.4.7
12
+
13
+ *Bug fixes*
14
+
15
+ - Fix `replace-force` deployment method override.
16
+ ```
17
+ /usr/local/bundle/gems/krane-2.4.6/lib/krane/resource_deployer.rb:119:in `block in deploy_resources': Unexpected deploy method! (:"replace-force") (ArgumentError)
18
+ ```
19
+ Dash (-) must be replaced with underscore (_) before applying it as method on kubernetes resource.
20
+
21
+ ## 2.4.6
22
+
23
+ *Bug fixes*
24
+
25
+ - Extend [#886](https://github.com/Shopify/krane/pull/886) to not only secrets but anything that doesn't match `failed to sync %s cache` [#886](https://github.com/Shopify/krane/pull/886)
26
+ It seems an issue when too many pods are referencing the same secret/configmap https://github.com/kubernetes/kubernetes/pull/74755, so instead of failing fast, it'll now let the resources attempt to succeed.
27
+ - Add missing unit test for above feature.
28
+
29
+ ## 2.4.5
30
+
31
+ *Bug fixes*
32
+
33
+ - Do not fail fast for CreateContainerConfigError when message include issues mounting the secret, to let the pods be recreated and possible succeed [#885](https://github.com/Shopify/krane/pull/885)
34
+
35
+ ## 2.4.4
36
+
37
+ *Enhancements*
38
+
39
+ - Improve DaemonSet rollout by ignoring `Evicted` Pods [#883](https://github.com/Shopify/krane/pull/883)
40
+
41
+ ## 2.4.3
42
+
43
+ *Enhancements*
44
+
45
+ - Improve DaemonSet rollout [#881](https://github.com/Shopify/krane/pull/881)
46
+
47
+ ## 2.4.2
48
+
49
+ *Bug fixes*
50
+
51
+ - Resolve errors for StatefulSet restart with `updateStrategy: OnDelete` [#876](https://github.com/Shopify/krane/pull/876)
52
+ - Timeouts during the "predeploy priority resources" phase now raise `DeploymentTimeoutError` instead of `FatalDeploymentError` [#874](https://github.com/Shopify/krane/pull/874)
53
+
3
54
  ## 2.4.1
4
55
 
5
56
  *Enhancements*
data/Gemfile CHANGED
@@ -3,3 +3,5 @@ source 'https://rubygems.org'
3
3
 
4
4
  # Specify your gem's dependencies in krane.gemspec
5
5
  gemspec
6
+
7
+ gem "ruby-lsp", "~> 0.2.0", :group => :development
data/dev.yml CHANGED
@@ -3,19 +3,10 @@ name: krane
3
3
  up:
4
4
  - ruby: '3.0.3' # Matches gemspec
5
5
  - bundler
6
- - custom:
7
- name: Install Kubernetes in Docker (KinD)
8
- met?: bin/kind version 2>&1 | grep -q v0.11.1
9
- meet: |
10
- mkdir -p bin
11
- curl -sLo bin/kind "https://github.com/kubernetes-sigs/kind/releases/download/v0.11.1/kind-darwin-amd64"
12
- chmod +x bin/kind
13
- - custom:
14
- name: Create KinD Cluster
15
- met?: bin/kind get clusters | grep -q krane
16
- meet: bin/kind create cluster --name krane --image "kindest/node:v1.22.0@sha256:b8bda84bb3a190e6e028b1760d277454a72267a5454b57db34437c34a588d047"
17
- down: |
18
- ((bin/kind get clusters | grep -q krane) && bin/kind delete cluster --name krane) || true
6
+ - podman
7
+ - kind:
8
+ name: krane
9
+ image: kindest/node:v1.22.0@sha256:b8bda84bb3a190e6e028b1760d277454a72267a5454b57db34437c34a588d047
19
10
  commands:
20
11
  test:
21
12
  run: bin/test
data/krane.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.required_ruby_version = '>= 2.6.0'
29
29
  spec.add_dependency("activesupport", ">= 5.0")
30
30
  spec.add_dependency("kubeclient", "~> 4.9")
31
- spec.add_dependency("googleauth", "~> 0.8")
31
+ spec.add_dependency("googleauth", "~> 1.2")
32
32
  spec.add_dependency("ejson", "~> 1.0")
33
33
  spec.add_dependency("colorize", "~> 0.8")
34
34
  spec.add_dependency("statsd-instrument", ['>= 2.8', "< 4"])
@@ -41,7 +41,8 @@ module Krane
41
41
  when '.json'
42
42
  bindings = parse_json(File.read(file_path))
43
43
  when '.yaml', '.yml'
44
- bindings = YAML.safe_load(File.read(file_path), [], [], true, file_path)
44
+ bindings = YAML.safe_load(File.read(file_path), permitted_classes: [], permitted_symbols: [],
45
+ aliases: true, filename: file_path)
45
46
  else
46
47
  raise ArgumentError, "Supplied file does not appear to be JSON or YAML"
47
48
  end
data/lib/krane/kubectl.rb CHANGED
@@ -82,9 +82,17 @@ module Krane
82
82
  def version_info
83
83
  @version_info ||=
84
84
  begin
85
- response, _, status = run("version", use_namespace: false, log_failure: true, attempts: 2)
85
+ response, _, status = run("version", output: "json", use_namespace: false, log_failure: true, attempts: 2)
86
86
  raise KubectlError, "Could not retrieve kubectl version info" unless status.success?
87
- extract_version_info_from_kubectl_response(response)
87
+
88
+ version_data = JSON.parse(response)
89
+ client_version = platform_agnostic_version(version_data.dig("clientVersion", "gitVersion").to_s)
90
+ server_version = platform_agnostic_version(version_data.dig("serverVersion", "gitVersion").to_s)
91
+ unless client_version && server_version
92
+ raise KubectlError, "Received invalid kubectl version data: #{version_data}"
93
+ end
94
+
95
+ { client: client_version, server: server_version }
88
96
  end
89
97
  end
90
98
 
@@ -127,15 +135,10 @@ module Krane
127
135
  end
128
136
  end
129
137
 
130
- def extract_version_info_from_kubectl_response(response)
131
- info = {}
132
- response.each_line do |l|
133
- match = l.match(/^(?<kind>Client|Server).* GitVersion:"v(?<version>\d+\.\d+\.\d+)/)
134
- if match
135
- info[match[:kind].downcase.to_sym] = Gem::Version.new(match[:version])
136
- end
138
+ def platform_agnostic_version(version_string)
139
+ if match = version_string.match(/v(?<version>\d+\.\d+\.\d+)/)
140
+ Gem::Version.new(match[:version])
137
141
  end
138
- info
139
142
  end
140
143
  end
141
144
  end
@@ -9,7 +9,8 @@ module Krane
9
9
  def sync(cache)
10
10
  super
11
11
  @pods = exists? ? find_pods(cache) : []
12
- @nodes = find_nodes(cache) if @nodes.blank?
12
+
13
+ @nodes = refresh_nodes(cache)
13
14
  end
14
15
 
15
16
  def status
@@ -58,7 +59,7 @@ module Krane
58
59
  def relevant_pods_ready?
59
60
  return true if rollout_data["desiredNumberScheduled"].to_i == rollout_data["numberReady"].to_i # all pods ready
60
61
  relevant_node_names = @nodes.map(&:name)
61
- considered_pods = @pods.select { |p| relevant_node_names.include?(p.node_name) }
62
+ considered_pods = @pods.select { |p| relevant_node_names.include?(p.node_name) && !p.evicted? }
62
63
  @logger.debug("DaemonSet is reporting #{rollout_data['numberReady']} pods ready." \
63
64
  " Considered #{considered_pods.size} pods out of #{@pods.size} for #{@nodes.size} nodes.")
64
65
  considered_pods.present? &&
@@ -66,9 +67,24 @@ module Krane
66
67
  rollout_data["numberReady"].to_i >= considered_pods.length
67
68
  end
68
69
 
70
+ def refresh_nodes(cache)
71
+ new_nodes = find_nodes(cache)
72
+ return new_nodes if @nodes.blank?
73
+
74
+ # Remove non-existent nodes
75
+ @nodes.select do |node|
76
+ new_nodes.find { |n| n.name == node.name } != nil
77
+ end
78
+ end
79
+
69
80
  def find_nodes(cache)
70
81
  all_nodes = cache.get_all(Node.kind)
71
- all_nodes.map { |node_data| Node.new(definition: node_data) }
82
+ all_nodes.each_with_object([]) do |node_data, relevant_nodes|
83
+ next if node_data.dig('spec', 'unschedulable').to_s.downcase == 'true'
84
+ cond = node_data.dig('status', 'conditions').find { |c| c['type'].downcase == 'ready' }
85
+ next if (!cond.nil? && cond['status'].downcase != 'true')
86
+ relevant_nodes << Node.new(definition: node_data)
87
+ end
72
88
  end
73
89
 
74
90
  def rollout_data
@@ -105,6 +105,10 @@ module Krane
105
105
  @instance_data.dig('spec', 'nodeName')
106
106
  end
107
107
 
108
+ def evicted?
109
+ phase == "Failed" && reason == "Evicted"
110
+ end
111
+
108
112
  private
109
113
 
110
114
  def failed_schedule_reason
@@ -225,7 +229,11 @@ module Krane
225
229
  elsif limbo_reason == "ErrImagePull" && limbo_message.match(/not found/i)
226
230
  "Failed to pull image #{@image}. "\
227
231
  "Did you wait for it to be built and pushed to the registry before deploying?"
228
- elsif limbo_reason == "CreateContainerConfigError"
232
+ # Only fail fast when message doesn't include `failed to sync %s cache`.
233
+ # It's possible that a secret/configmap is still trying to be mounted to the pod, it seems related
234
+ # to too many pods referencing the same secret/configmap: https://github.com/kubernetes/kubernetes/pull/74755
235
+ # Error message format source: https://github.com/kubernetes/kubernetes/pull/75260
236
+ elsif limbo_reason == "CreateContainerConfigError" && !limbo_message.match("failed to sync (.*?) cache")
229
237
  "Failed to generate container configuration: #{limbo_message}"
230
238
  elsif @status.dig("lastState", "terminated", "reason") == "ContainerCannotRun"
231
239
  # ref: https://github.com/kubernetes/kubernetes/blob/562e721ece8a16e05c7e7d6bdd6334c910733ab2/pkg/kubelet/dockershim/docker_container.go#L353
@@ -19,6 +19,9 @@ module Krane
19
19
  end
20
20
 
21
21
  def deploy_succeeded?
22
+ success = observed_generation == current_generation &&
23
+ desired_replicas == status_data['readyReplicas'].to_i &&
24
+ status_data['currentRevision'] == status_data['updateRevision']
22
25
  if update_strategy == ONDELETE
23
26
  # Gem cannot monitor update since it doesn't occur until delete
24
27
  unless @success_assumption_warning_shown
@@ -27,11 +30,10 @@ module Krane
27
30
  "Consider switching to rollingUpdate.")
28
31
  @success_assumption_warning_shown = true
29
32
  end
33
+ else
34
+ success &= desired_replicas == status_data['currentReplicas'].to_i
30
35
  end
31
- observed_generation == current_generation &&
32
- status_data['currentRevision'] == status_data['updateRevision'] &&
33
- desired_replicas == status_data['readyReplicas'].to_i &&
34
- desired_replicas == status_data['currentReplicas'].to_i
36
+ success
35
37
  end
36
38
 
37
39
  def deploy_failed?
@@ -250,7 +250,7 @@ module Krane
250
250
  end
251
251
 
252
252
  def deploy_method_override
253
- krane_annotation_value(DEPLOY_METHOD_OVERRIDE_ANNOTATION)&.to_sym
253
+ krane_annotation_value(DEPLOY_METHOD_OVERRIDE_ANNOTATION)&.gsub("-", "_")&.to_sym
254
254
  end
255
255
 
256
256
  def sync_debug_info(kubectl)
@@ -70,6 +70,7 @@ module Krane
70
70
  r.sync_debug_info(kubectl)
71
71
  end
72
72
  failed_resources.each { |r| logger.summary.add_paragraph(r.debug_message) }
73
+ raise DeploymentTimeoutError if failed_resources.all?(&:deploy_timed_out?)
73
74
  raise FatalDeploymentError, "Failed to deploy #{fail_count} priority #{'resource'.pluralize(fail_count)}"
74
75
  end
75
76
  logger.blank_line
@@ -213,7 +213,7 @@ module Krane
213
213
  def delete_statefulset_pods(record)
214
214
  pods = kubeclient.get_pods(namespace: record.metadata.namespace)
215
215
  pods.select! do |pod|
216
- pod.metadata.ownerReferences.find { |ref| ref.uid == record.metadata.uid }
216
+ pod.metadata&.ownerReferences&.find { |ref| ref.uid == record.metadata.uid }
217
217
  end
218
218
  pods.each { |pod| kubeclient.delete_pod(pod.metadata.name, pod.metadata.namespace) }
219
219
  end
data/lib/krane/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Krane
3
- VERSION = "2.4.1"
3
+ VERSION = "2.4.9"
4
4
  end
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: 2.4.1
4
+ version: 2.4.9
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: 2022-02-02 00:00:00.000000000 Z
13
+ date: 2022-07-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -46,14 +46,14 @@ dependencies:
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '0.8'
49
+ version: '1.2'
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: '0.8'
56
+ version: '1.2'
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: ejson
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -526,7 +526,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
526
526
  - !ruby/object:Gem::Version
527
527
  version: '0'
528
528
  requirements: []
529
- rubygems_version: 3.2.20
529
+ rubygems_version: 3.3.3
530
530
  signing_key:
531
531
  specification_version: 4
532
532
  summary: A command line tool that helps you ship changes to a Kubernetes namespace