krane 3.2.0 → 3.4.0

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: c1c5ae5aab30f6f9065bdf415b4fe94b7b82c8c0a05aecc582a5363349221be8
4
- data.tar.gz: 79d0aefc5abb7671c5c366a02648e183589d1cb90991912f381ac0b6a46c5af6
3
+ metadata.gz: 0a400c15e247a60bf8596665ddf2737abb44c2418358212e689890eb2178956f
4
+ data.tar.gz: '0386e1417ba00c97add6aa7184176785f82d05de5453140a8806540833c85f46'
5
5
  SHA512:
6
- metadata.gz: 33c08fdcb4e09e571667872ea761f046977516e1d882d29638faf54f9f58b00ae0534de616a5f304a7231f2820c2a6938ae7a3eaea761987c619b4f6ffc13693
7
- data.tar.gz: 96d52d7e49b0d50bd12e6c28f8ec65e3db86e3b66704149a6ef7756119a168ca4326d0e7aeb897489a2a04a8a4d0e56e7ca0b6254d88e48e682b134ee7b921a9
6
+ metadata.gz: a8b4c706a3918d6d3b66f098ae03c1e02680d59bef3f8eab34248997bfc11e512206f1b1d1794f50f12965e7a0cffbb2df2293b4639dd28b4b8526db881cf315
7
+ data.tar.gz: 7d113bfa20d8dec893fa3494ea7f55a9bf89c3a59ca7a461e1076c5fed37c2725b495a96efa5034c18b857819c96f5803045dec444a3c205e70f647b162f8106
data/.github/CODEOWNERS CHANGED
@@ -1 +1 @@
1
- * @Shopify/app-lifecycle
1
+ * @Shopify/infrastructure-tooling
@@ -0,0 +1,18 @@
1
+ name: Project automations
2
+ on:
3
+ issues:
4
+ types:
5
+ - opened
6
+ - reopened
7
+ env:
8
+ PROJECT_URL: https://github.com/orgs/Shopify/projects/2279
9
+
10
+ jobs:
11
+ add-to-project:
12
+ name: Issue or PR opened
13
+ runs-on: shopify-ubuntu-latest
14
+ steps:
15
+ - uses: actions/add-to-project@v0.4.0 # https://github.com/actions/add-to-project/tree/v0.4.0
16
+ with:
17
+ project-url: ${{ env.PROJECT_URL }}
18
+ github-token: ${{ secrets.SHOPIFY_GH_ACCESS_TOKEN }}
@@ -16,10 +16,13 @@ jobs:
16
16
  - "3.0.4"
17
17
  - "2.7.6"
18
18
  kubernetes_version:
19
+ - "1.27.3"
19
20
  - "1.26.4"
20
21
  - "1.24.13"
21
22
  - "1.23.17"
22
23
  include:
24
+ - kubernetes_version: "1.27.3"
25
+ kind_image: "kindest/node:v1.27.3@sha256:9dd3392d79af1b084671b05bcf65b21de476256ad1dcc853d9f3b10b4ac52dde"
23
26
  - kubernetes_version: "1.26.4"
24
27
  kind_image: "kindest/node:v1.26.4@sha256:a539833d26264444ab3b8f5e56e23fa3361436445fa23c864e6dec622458858f"
25
28
  - kubernetes_version: "1.24.13"
data/1.0-Upgrade.md CHANGED
@@ -7,7 +7,7 @@
7
7
  * There are breaking changes in the public API (such as the renaming of the `KubernetesDeploy` namespace to `Krane`, and the change in default values for different arguments of the public interface).
8
8
  * StatsD metrics will now be generated with the `krane` prefix.
9
9
  * `krane deploy` now considers all namespaced resources eligible for pruning, including
10
- custom resources. See [blacklist](https://github.com/Shopify/krane/blob/master/lib/krane/cluster_resource_discovery.rb#L20) for exceptions.
10
+ custom resources. See [blacklist](https://github.com/Shopify/krane/blob/main/lib/krane/cluster_resource_discovery.rb#L20) for exceptions.
11
11
  * `kubernetes-deploy` (now `krane deploy`) / `DeployTask` can no longer deploy global (non-namespaced) resources. A new command called `krane global-deploy` and a related class called `GlobalDeployTask` were added to replace that feature.
12
12
  * `krane deploy` will not render erb templates. Use `krane render | krane deploy --stdin` to reproduce this functionality.
13
13
  * If you attempt to install two gems that have conflicting executables, `gem install` will warn you but the most recently installed one will win.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## next
2
2
 
3
+ # 3.4.0
4
+
5
+ - Use `prune-allowlist` instead of `prune-whitelist` for 1.26+ clusters. Clusters running 1.25 or less will continue to use `--prune-whitelist`. [#940](https://github.com/Shopify/krane/pull/940)
6
+
7
+ ## 3.3.0
8
+
9
+ *Enhancements*
10
+
11
+ - Enable detection of successful StatefulSet deploys when the `updateStrategy` is `onDelete`, behind an annotation. [#926](https://github.com/Shopify/krane/pull/926)
12
+
3
13
  ## 3.2.0
4
14
 
5
15
  *Enhancements*
@@ -282,7 +292,7 @@ It seems an issue when too many pods are referencing the same secret/configmap h
282
292
  # 1.0.0
283
293
 
284
294
  We've renamed the gem and cli to Krane.
285
- See our [migration guide](https://github.com/Shopify/krane/blob/master/1.0-Upgrade.md) to help navigate the breaking changes.
295
+ See our [migration guide](https://github.com/Shopify/krane/blob/main/1.0-Upgrade.md) to help navigate the breaking changes.
286
296
 
287
297
  ## 1.0.0.pre.2
288
298
 
data/CONTRIBUTING.md CHANGED
@@ -22,7 +22,7 @@ The following is a set of guidelines for contributing to krane. Please take a mo
22
22
  * [CI (External contributors)](#ci-external-contributors)
23
23
  ## Code of Conduct
24
24
 
25
- This project and everyone participating in it are governed by the [Code of Conduct](https://github.com/Shopify/krane/blob/master/CODE_OF_CONDUCT.md).
25
+ This project and everyone participating in it are governed by the [Code of Conduct](https://github.com/Shopify/krane/blob/main/CODE_OF_CONDUCT.md).
26
26
  By participating, you are expected to uphold this code. Please report unacceptable
27
27
  behavior to [krane@shopify.com](mailto:krane@shopify.com).
28
28
 
@@ -95,9 +95,9 @@ This gem uses subclasses of `KubernetesResource` to implement custom success/fai
95
95
  * `deploy_failed?`
96
96
  3. Adjust the `TIMEOUT` constant to an appropriate value for this type.
97
97
  4. Add the new class to list of resources in
98
- [`deploy_task.rb`](https://github.com/Shopify/krane/blob/master/lib/krane/deploy_task.rb#L8)
99
- 5. Add the new resource to the [prune whitelist](https://github.com/Shopify/krane/blob/master/lib/krane/deploy_task.rb#L81)
100
- 6. Add a basic example of the type to the hello-cloud [fixture set](https://github.com/Shopify/krane/tree/master/test/fixtures/hello-cloud) and appropriate assertions to `#assert_all_up` in [`hello_cloud.rb`](https://github.com/Shopify/krane/blob/master/test/helpers/fixture_sets/hello_cloud.rb). This will get you coverage in several existing tests, such as `test_full_hello_cloud_set_deploy_succeeds`.
98
+ [`deploy_task.rb`](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L8)
99
+ 5. Add the new resource to the [prune whitelist](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L81)
100
+ 6. Add a basic example of the type to the hello-cloud [fixture set](https://github.com/Shopify/krane/tree/main/test/fixtures/hello-cloud) and appropriate assertions to `#assert_all_up` in [`hello_cloud.rb`](https://github.com/Shopify/krane/blob/main/test/helpers/fixture_sets/hello_cloud.rb). This will get you coverage in several existing tests, such as `test_full_hello_cloud_set_deploy_succeeds`.
101
101
  7. Add tests for any edge cases you foresee.
102
102
 
103
103
  ### Contributor License Agreement
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # krane [![Build status](https://badge.buildkite.com/35c56e797c3bbd6ba50053aefdded0715898cd8e8c86f7e462.svg?branch=master)](https://buildkite.com/shopify/krane)
1
+ # krane [![Build status](https://badge.buildkite.com/35c56e797c3bbd6ba50053aefdded0715898cd8e8c86f7e462.svg?branch=main)](https://buildkite.com/shopify/krane)
2
2
 
3
- > This project used to be called `kubernetes-deploy`. Check out our [migration guide](https://github.com/Shopify/krane/blob/master/1.0-Upgrade.md) for more information including details about breaking changes.
3
+ > This project used to be called `kubernetes-deploy`. Check out our [migration guide](https://github.com/Shopify/krane/blob/main/1.0-Upgrade.md) for more information including details about breaking changes.
4
4
 
5
5
 
6
6
  `krane` is a command line tool that helps you ship changes to a Kubernetes namespace and understand the result. At Shopify, we use it within our much-beloved, open-source [Shipit](https://github.com/Shopify/shipit-engine#kubernetes) deployment app.
@@ -93,6 +93,7 @@ Krane provides support for official upstream supported versions [Kubernetes](htt
93
93
  | 1.24 | Yes | -- |
94
94
  | 1.25 | No | -- |
95
95
  | 1.26 | Yes | -- |
96
+ | 1.27 | Yes | -- |
96
97
 
97
98
  ## Installation
98
99
 
@@ -155,14 +156,13 @@ If you want dynamic templates, you may render ERB with `krane render` and then p
155
156
  - `krane.shopify.io/required-rollout`: Modifies how much of the rollout needs to finish
156
157
  before the deployment is considered successful.
157
158
  - _Compatibility_: Deployment
158
- - `full`: The deployment is successful when all pods in the new `replicaSet` are ready.
159
- - `none`: The deployment is successful as soon as the new `replicaSet` is created for the deployment.
160
- - `maxUnavailable`: The deploy is successful when minimum availability is reached in the new `replicaSet`.
161
- In other words, the number of new pods that must be ready is equal to `spec.replicas` - `strategy.RollingUpdate.maxUnavailable`
162
- (converted from percentages by rounding up, if applicable). This option is only valid for deployments
163
- that use the `RollingUpdate` strategy.
164
- - Percent (e.g. 90%): The deploy is successful when the number of new pods that are ready is equal to
165
- `spec.replicas` * Percent.
159
+ - `full`: The deployment is successful when all pods in the new `replicaSet` are ready.
160
+ - `none`: The deployment is successful as soon as the new `replicaSet` is created for the deployment.
161
+ - `maxUnavailable`: The deploy is successful when minimum availability is reached in the new `replicaSet`.
162
+ In other words, the number of new pods that must be ready is equal to `spec.replicas` - `strategy.RollingUpdate.maxUnavailable` (converted from percentages by rounding up, if applicable). This option is only valid for deployments that use the `RollingUpdate` strategy.
163
+ - Percent (e.g. 90%): The deploy is successful when the number of new pods that are ready is equal to `spec.replicas` * Percent.
164
+ - _Compatibility_: StatefulSet
165
+ - `full`: The deployment is successful when all pods are ready.
166
166
  - `krane.shopify.io/predeployed`: Causes a Custom Resource to be deployed in the pre-deploy phase.
167
167
  - _Compatibility_: Custom Resource Definition
168
168
  - _Default_: `true`
@@ -337,7 +337,7 @@ status:
337
337
 
338
338
  ### Deploy walkthrough
339
339
 
340
- Let's walk through what happens when you run the `deploy` task with [this directory of templates](https://github.com/Shopify/krane/tree/master/test/fixtures/hello-cloud). This particular example uses ERB templates as well, so we'll use the [krane render](#krane-render) task to achieve that.
340
+ Let's walk through what happens when you run the `deploy` task with [this directory of templates](https://github.com/Shopify/krane/tree/main/test/fixtures/hello-cloud). This particular example uses ERB templates as well, so we'll use the [krane render](#krane-render) task to achieve that.
341
341
 
342
342
  You can test this out for yourself by running the following command:
343
343
 
@@ -404,7 +404,7 @@ In this phase, we:
404
404
 
405
405
  Just like in the previous phase, we essentially run `kubectl apply` on those templates and periodically check the cluster for the current status of each resource so we can display error or success information.
406
406
 
407
- If pruning is enabled (which, again, is the default), any [kind not listed in the blacklist](https://github.com/Shopify/krane/blob/master/lib/krane/cluster_resource_discovery.rb#L20) that we can find in the namespace but not in the templates will be removed. A particular message about pruning will be printed in the next phase if any resource matches this criteria.
407
+ If pruning is enabled (which, again, is the default), any [kind not listed in the blacklist](https://github.com/Shopify/krane/blob/main/lib/krane/cluster_resource_discovery.rb#L20) that we can find in the namespace but not in the templates will be removed. A particular message about pruning will be printed in the next phase if any resource matches this criteria.
408
408
 
409
409
  #### Result
410
410
 
@@ -654,13 +654,13 @@ This is a limitation of the current implementation.
654
654
  # Contributing
655
655
 
656
656
  We :heart: contributors! To make it easier for you and us we've written a
657
- [Contributing Guide](https://github.com/Shopify/krane/blob/master/CONTRIBUTING.md)
657
+ [Contributing Guide](https://github.com/Shopify/krane/blob/main/CONTRIBUTING.md)
658
658
 
659
659
 
660
660
  You can also reach out to us on our slack channel, #krane, at https://kubernetes.slack.com. All are welcome!
661
661
 
662
662
  ## Code of Conduct
663
- Everyone is expected to follow our [Code of Conduct](https://github.com/Shopify/krane/blob/master/CODE_OF_CONDUCT.md).
663
+ Everyone is expected to follow our [Code of Conduct](https://github.com/Shopify/krane/blob/main/CODE_OF_CONDUCT.md).
664
664
 
665
665
 
666
666
  # License
data/krane.gemspec CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
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"])
35
- spec.add_dependency("oj", "~> 3.0")
35
+ spec.add_dependency("multi_json")
36
36
  spec.add_dependency("concurrent-ruby", "~> 1.1")
37
37
  spec.add_dependency("jsonpath", "~> 1.0")
38
38
  spec.add_dependency("thor", ">= 1.0", "< 2.0")
@@ -43,11 +43,11 @@ Gem::Specification.new do |spec|
43
43
  spec.add_development_dependency("yard")
44
44
 
45
45
  # Test framework
46
- spec.add_development_dependency("minitest", "~> 5.12")
46
+ spec.add_development_dependency("minitest", "~> 5.19")
47
47
  spec.add_development_dependency("minitest-stub-const", "~> 0.6")
48
48
  spec.add_development_dependency("minitest-reporters")
49
- spec.add_development_dependency("mocha", "~> 1.5")
50
- spec.add_development_dependency("webmock", "~> 3.0")
49
+ spec.add_development_dependency("mocha", "~> 2.1")
50
+ spec.add_development_dependency("webmock", "~> 3.18")
51
51
  spec.add_development_dependency("timecop")
52
52
 
53
53
  # Debugging and analysis
@@ -54,14 +54,14 @@ module Krane
54
54
  end
55
55
 
56
56
  def parse_json(string)
57
- bindings = JSON.parse(string)
57
+ bindings = MultiJson.load(string)
58
58
 
59
59
  unless bindings.is_a?(Hash)
60
60
  raise ArgumentError, "Expected JSON data to be a hash."
61
61
  end
62
62
 
63
63
  bindings
64
- rescue JSON::ParserError
64
+ rescue MultiJson::ParseError
65
65
  nil
66
66
  end
67
67
 
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  require 'krane'
3
- require 'krane/oj'
4
- require 'thor'
5
- require 'krane/cli/version_command'
6
- require 'krane/cli/restart_command'
7
- require 'krane/cli/run_command'
8
- require 'krane/cli/render_command'
9
3
  require 'krane/cli/deploy_command'
10
4
  require 'krane/cli/global_deploy_command'
5
+ require 'krane/cli/render_command'
6
+ require 'krane/cli/restart_command'
7
+ require 'krane/cli/run_command'
8
+ require 'krane/cli/version_command'
9
+ require 'multi_json'
10
+ require 'thor'
11
11
 
12
12
  module Krane
13
13
  module CLI
@@ -54,7 +54,7 @@ module Krane
54
54
  @api_path_cache["/"] ||= begin
55
55
  raw_json, err, st = kubectl.run("get", "--raw", base_api_path, attempts: 5, use_namespace: false)
56
56
  paths = if st.success?
57
- JSON.parse(raw_json)["paths"]
57
+ MultiJson.load(raw_json)["paths"]
58
58
  else
59
59
  raise FatalKubeAPIError, "Error retrieving raw path /: #{err}"
60
60
  end
@@ -66,7 +66,7 @@ module Krane
66
66
  @api_path_cache[path] ||= begin
67
67
  raw_json, err, st = kubectl.run("get", "--raw", path, attempts: 2, use_namespace: false)
68
68
  if st.success?
69
- JSON.parse(raw_json)
69
+ MultiJson.load(raw_json)
70
70
  else
71
71
  logger.warn("Error retrieving api path: #{err}")
72
72
  {}
@@ -92,7 +92,7 @@ module Krane
92
92
  raw_json, err, st = kubectl.run("get", "CustomResourceDefinition", output: "json", attempts: 5,
93
93
  use_namespace: false)
94
94
  if st.success?
95
- JSON.parse(raw_json)["items"]
95
+ MultiJson.load(raw_json)["items"]
96
96
  else
97
97
  raise FatalKubeAPIError, "Error retrieving CustomResourceDefinition: #{err}"
98
98
  end
@@ -77,7 +77,7 @@ module Krane
77
77
  Hash[before_crs + crs + after_crs]
78
78
  end
79
79
 
80
- def prune_whitelist
80
+ def prune_allowlist
81
81
  cluster_resource_discoverer.prunable_resources(namespaced: true)
82
82
  end
83
83
 
@@ -192,7 +192,7 @@ module Krane
192
192
 
193
193
  def resource_deployer
194
194
  @resource_deployer ||= Krane::ResourceDeployer.new(task_config: @task_config,
195
- prune_whitelist: prune_whitelist, global_timeout: @global_timeout,
195
+ prune_allowlist: prune_allowlist, global_timeout: @global_timeout,
196
196
  selector: @selector, statsd_tags: statsd_tags, current_sha: @current_sha)
197
197
  end
198
198
 
@@ -328,7 +328,7 @@ module Krane
328
328
  @namespace_definition ||= begin
329
329
  definition, _err, st = kubectl.run("get", "namespace", @namespace, use_namespace: false,
330
330
  log_failure: true, raise_if_not_found: true, attempts: 3, output: 'json')
331
- st.success? ? JSON.parse(definition, symbolize_names: true) : nil
331
+ st.success? ? MultiJson.load(definition, symbolize_names: true) : nil
332
332
  end
333
333
  rescue Kubectl::ResourceNotFoundError
334
334
  nil
@@ -362,7 +362,7 @@ module Krane
362
362
  unless st.success?
363
363
  raise EjsonSecretError, "Error retrieving Secret/#{EjsonSecretProvisioner::EJSON_KEYS_SECRET}: #{err}"
364
364
  end
365
- JSON.parse(out)
365
+ MultiJson.load(out)
366
366
  end
367
367
  end
368
368
 
@@ -117,8 +117,8 @@ module Krane
117
117
 
118
118
  def load_ejson_from_file
119
119
  return {} unless File.exist?(@ejson_file)
120
- JSON.parse(File.read(@ejson_file))
121
- rescue JSON::ParserError => e
120
+ MultiJson.load(File.read(@ejson_file))
121
+ rescue MultiJson::ParseError => e
122
122
  raise EjsonSecretError, "Failed to parse encrypted ejson:\n #{e}"
123
123
  end
124
124
 
@@ -139,8 +139,8 @@ module Krane
139
139
  msg = err.presence || out
140
140
  raise EjsonSecretError, msg
141
141
  end
142
- JSON.parse(out)
143
- rescue JSON::ParserError
142
+ MultiJson.load(out)
143
+ rescue MultiJson::ParseError
144
144
  raise EjsonSecretError, "Failed to parse decrypted ejson"
145
145
  end
146
146
 
@@ -108,7 +108,7 @@ module Krane
108
108
 
109
109
  def deploy!(resources, verify_result, prune)
110
110
  resource_deployer = ResourceDeployer.new(task_config: @task_config,
111
- prune_whitelist: prune_whitelist, global_timeout: @global_timeout,
111
+ prune_allowlist: prune_allowlist, global_timeout: @global_timeout,
112
112
  selector: @selector, statsd_tags: statsd_tags)
113
113
  resource_deployer.deploy!(resources, verify_result, prune)
114
114
  end
@@ -194,7 +194,7 @@ module Krane
194
194
  @kubectl ||= Kubectl.new(task_config: @task_config, log_failure_by_default: true)
195
195
  end
196
196
 
197
- def prune_whitelist
197
+ def prune_allowlist
198
198
  cluster_resource_discoverer.prunable_resources(namespaced: false)
199
199
  end
200
200
 
data/lib/krane/kubectl.rb CHANGED
@@ -12,6 +12,7 @@ module Krane
12
12
  DEFAULT_TIMEOUT = 15
13
13
  MAX_RETRY_DELAY = 16
14
14
  SERVER_DRY_RUN_MIN_VERSION = "1.13"
15
+ ALLOW_LIST_MIN_VERSION = "1.26"
15
16
 
16
17
  class ResourceNotFoundError < StandardError; end
17
18
 
@@ -85,7 +86,7 @@ module Krane
85
86
  response, _, status = run("version", output: "json", use_namespace: false, log_failure: true, attempts: 2)
86
87
  raise KubectlError, "Could not retrieve kubectl version info" unless status.success?
87
88
 
88
- version_data = JSON.parse(response)
89
+ version_data = MultiJson.load(response)
89
90
  client_version = platform_agnostic_version(version_data.dig("clientVersion", "gitVersion").to_s)
90
91
  server_version = platform_agnostic_version(version_data.dig("serverVersion", "gitVersion").to_s)
91
92
  unless client_version && server_version
@@ -112,6 +113,14 @@ module Krane
112
113
  "--dry-run=server"
113
114
  end
114
115
 
116
+ def allowlist_flag
117
+ if client_version >= Gem::Version.new(ALLOW_LIST_MIN_VERSION)
118
+ "--prune-allowlist"
119
+ else
120
+ "--prune-whitelist"
121
+ end
122
+ end
123
+
115
124
  private
116
125
 
117
126
  def build_command_from_options(args, use_namespace, use_context, output)
@@ -10,6 +10,7 @@ module Krane
10
10
  )
11
11
 
12
12
  attr_accessor :stream_logs
13
+ attr_reader :definition
13
14
 
14
15
  def initialize(namespace:, context:, definition:, logger:,
15
16
  statsd_tags: nil, parent: nil, deploy_started_at: nil, stream_logs: false)
@@ -5,6 +5,7 @@ module Krane
5
5
  TIMEOUT = 10.minutes
6
6
  ONDELETE = 'OnDelete'
7
7
  SYNC_DEPENDENCIES = %w(Pod)
8
+ REQUIRED_ROLLOUT_TYPES = %w(full).freeze
8
9
  attr_reader :pods
9
10
 
10
11
  def sync(cache)
@@ -19,25 +20,35 @@ module Krane
19
20
  end
20
21
 
21
22
  def deploy_succeeded?
22
- success = observed_generation == current_generation &&
23
- desired_replicas == status_data['readyReplicas'].to_i &&
24
- status_data['currentRevision'] == status_data['updateRevision']
25
- if update_strategy == ONDELETE
26
- # Gem cannot monitor update since it doesn't occur until delete
23
+ success = observed_generation == current_generation
24
+
25
+ @pods.each do |pod|
26
+ success &= pod.definition["metadata"]["labels"]["controller-revision-hash"] == status_data['updateRevision']
27
+ end
28
+
29
+ if update_strategy == 'RollingUpdate'
30
+ success &= status_data['currentRevision'] == status_data['updateRevision']
31
+ success &= desired_replicas == status_data['readyReplicas'].to_i
32
+ success &= desired_replicas == status_data['currentReplicas'].to_i
33
+
34
+ elsif update_strategy == ONDELETE
27
35
  unless @success_assumption_warning_shown
28
36
  @logger.warn("WARNING: Your StatefulSet's updateStrategy is set to OnDelete, "\
29
- "which means updates will not be applied until its pods are deleted. "\
30
- "Consider switching to rollingUpdate.")
37
+ "which means the deployment won't succeed until all pods are updated by deletion.")
31
38
  @success_assumption_warning_shown = true
32
39
  end
33
- else
34
- success &= desired_replicas == status_data['currentReplicas'].to_i
40
+
41
+ if required_rollout == 'full'
42
+ success &= desired_replicas == status_data['readyReplicas'].to_i
43
+ success &= desired_replicas == status_data['updatedReplicas'].to_i
44
+ end
35
45
  end
46
+
36
47
  success
37
48
  end
38
49
 
39
50
  def deploy_failed?
40
- return false if update_strategy == ONDELETE
51
+ return false if update_strategy == ONDELETE && required_rollout != 'full'
41
52
  pods.present? && pods.any?(&:deploy_failed?) &&
42
53
  observed_generation == current_generation
43
54
  end
@@ -67,5 +78,9 @@ module Krane
67
78
  pod_data["metadata"]["ownerReferences"].any? { |ref| ref["uid"] == @instance_data["metadata"]["uid"] } &&
68
79
  @instance_data["status"]["currentRevision"] == pod_data["metadata"]["labels"]["controller-revision-hash"]
69
80
  end
81
+
82
+ def required_rollout
83
+ krane_annotation_value("required-rollout") || nil
84
+ end
70
85
  end
71
86
  end
@@ -64,7 +64,7 @@ module Krane
64
64
  raise KubectlError unless st.success?
65
65
 
66
66
  instances = {}
67
- JSON.parse(raw_json)["items"].each do |resource|
67
+ MultiJson.load(raw_json)["items"].each do |resource|
68
68
  resource_name = resource.dig("metadata", "name")
69
69
  instances[resource_name] = resource
70
70
  end
@@ -11,9 +11,9 @@ module Krane
11
11
  delegate :logger, to: :@task_config
12
12
  attr_reader :statsd_tags
13
13
 
14
- def initialize(task_config:, prune_whitelist:, global_timeout:, current_sha: nil, selector:, statsd_tags:)
14
+ def initialize(task_config:, prune_allowlist:, global_timeout:, current_sha: nil, selector:, statsd_tags:)
15
15
  @task_config = task_config
16
- @prune_whitelist = prune_whitelist
16
+ @prune_allowlist = prune_allowlist
17
17
  @global_timeout = global_timeout
18
18
  @current_sha = current_sha
19
19
  @selector = selector
@@ -102,7 +102,7 @@ module Krane
102
102
  # Apply can be done in one large batch, the rest have to be done individually
103
103
  applyables, individuals = resources.partition { |r| r.deploy_method == :apply }
104
104
  # Prunable resources should also applied so that they can be pruned
105
- pruneable_types = @prune_whitelist.map { |t| t.split("/").last }
105
+ pruneable_types = @prune_allowlist.map { |t| t.split("/").last }
106
106
  applyables += individuals.select { |r| pruneable_types.include?(r.type) && !r.deploy_method_override }
107
107
 
108
108
  individuals.each do |individual_resource|
@@ -147,14 +147,15 @@ module Krane
147
147
  r.deploy_started_at = Time.now.utc unless dry_run
148
148
  end
149
149
  command.push("-f", tmp_dir)
150
- if prune && @prune_whitelist.present?
150
+ if prune && @prune_allowlist.present?
151
151
  command.push("--prune")
152
152
  if @selector
153
153
  command.push("--selector", @selector.to_s)
154
154
  else
155
155
  command.push("--all")
156
156
  end
157
- @prune_whitelist.each { |type| command.push("--prune-whitelist=#{type}") }
157
+ allow_list_flag = kubectl.allowlist_flag
158
+ @prune_allowlist.each { |type| command.push("#{allow_list_flag}=#{type}") }
158
159
  end
159
160
 
160
161
  command.push(kubectl.dry_run_flag) if dry_run
@@ -252,7 +253,7 @@ module Krane
252
253
  # For resources that rely on a generateName attribute, we get the `name` from the result of the call to `create`
253
254
  # We must explicitly set this name value so that the `apply` step for pruning can run successfully
254
255
  if status.success? && resource.uses_generate_name?
255
- resource.use_generated_name(JSON.parse(out))
256
+ resource.use_generated_name(MultiJson.load(out))
256
257
  end
257
258
 
258
259
  [err, status]
@@ -11,7 +11,7 @@ module Krane
11
11
  def from_annotation(conditions_string)
12
12
  return new(default_conditions) if conditions_string.downcase.strip == "true"
13
13
 
14
- conditions = JSON.parse(conditions_string).slice('success_conditions', 'failure_conditions')
14
+ conditions = MultiJson.load(conditions_string).slice('success_conditions', 'failure_conditions')
15
15
  conditions.deep_symbolize_keys!
16
16
 
17
17
  # Create JsonPath objects
@@ -26,7 +26,7 @@ module Krane
26
26
  end
27
27
 
28
28
  new(conditions)
29
- rescue JSON::ParserError => e
29
+ rescue MultiJson::ParseError => e
30
30
  raise RolloutConditionsError, "Rollout conditions are not valid JSON: #{e}"
31
31
  rescue StandardError => e
32
32
  raise RolloutConditionsError,
data/lib/krane/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Krane
3
- VERSION = "3.2.0"
3
+ VERSION = "3.4.0"
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: 3.2.0
4
+ version: 3.4.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: 2023-06-14 00:00:00.000000000 Z
13
+ date: 2023-12-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -103,19 +103,19 @@ dependencies:
103
103
  - !ruby/object:Gem::Version
104
104
  version: '4'
105
105
  - !ruby/object:Gem::Dependency
106
- name: oj
106
+ name: multi_json
107
107
  requirement: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - "~>"
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
- version: '3.0'
111
+ version: '0'
112
112
  type: :runtime
113
113
  prerelease: false
114
114
  version_requirements: !ruby/object:Gem::Requirement
115
115
  requirements:
116
- - - "~>"
116
+ - - ">="
117
117
  - !ruby/object:Gem::Version
118
- version: '3.0'
118
+ version: '0'
119
119
  - !ruby/object:Gem::Dependency
120
120
  name: concurrent-ruby
121
121
  requirement: !ruby/object:Gem::Requirement
@@ -212,14 +212,14 @@ dependencies:
212
212
  requirements:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
- version: '5.12'
215
+ version: '5.19'
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
- version: '5.12'
222
+ version: '5.19'
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: minitest-stub-const
225
225
  requirement: !ruby/object:Gem::Requirement
@@ -254,28 +254,28 @@ dependencies:
254
254
  requirements:
255
255
  - - "~>"
256
256
  - !ruby/object:Gem::Version
257
- version: '1.5'
257
+ version: '2.1'
258
258
  type: :development
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
262
  - - "~>"
263
263
  - !ruby/object:Gem::Version
264
- version: '1.5'
264
+ version: '2.1'
265
265
  - !ruby/object:Gem::Dependency
266
266
  name: webmock
267
267
  requirement: !ruby/object:Gem::Requirement
268
268
  requirements:
269
269
  - - "~>"
270
270
  - !ruby/object:Gem::Version
271
- version: '3.0'
271
+ version: '3.18'
272
272
  type: :development
273
273
  prerelease: false
274
274
  version_requirements: !ruby/object:Gem::Requirement
275
275
  requirements:
276
276
  - - "~>"
277
277
  - !ruby/object:Gem::Version
278
- version: '3.0'
278
+ version: '3.18'
279
279
  - !ruby/object:Gem::Dependency
280
280
  name: timecop
281
281
  requirement: !ruby/object:Gem::Requirement
@@ -414,6 +414,7 @@ files:
414
414
  - ".github/CODEOWNERS"
415
415
  - ".github/ISSUE_TEMPLATE.md"
416
416
  - ".github/pull_request_template.md"
417
+ - ".github/workflows/add-to-project.yml"
417
418
  - ".github/workflows/ci.yml"
418
419
  - ".github/workflows/cla.yml"
419
420
  - ".gitignore"
@@ -487,7 +488,6 @@ files:
487
488
  - lib/krane/kubernetes_resource/service_account.rb
488
489
  - lib/krane/kubernetes_resource/stateful_set.rb
489
490
  - lib/krane/label_selector.rb
490
- - lib/krane/oj.rb
491
491
  - lib/krane/options_helper.rb
492
492
  - lib/krane/psych_k8s_compatibility.rb
493
493
  - lib/krane/remote_logs.rb
@@ -525,7 +525,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
525
525
  - !ruby/object:Gem::Version
526
526
  version: '0'
527
527
  requirements: []
528
- rubygems_version: 3.4.13
528
+ rubygems_version: 3.4.22
529
529
  signing_key:
530
530
  specification_version: 4
531
531
  summary: A command line tool that helps you ship changes to a Kubernetes namespace
data/lib/krane/oj.rb DELETED
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'oj'
3
-
4
- Oj.mimic_JSON