krane 2.4.1 → 2.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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