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 +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/add-to-project.yml +18 -0
- data/.github/workflows/ci.yml +3 -0
- data/1.0-Upgrade.md +1 -1
- data/CHANGELOG.md +11 -1
- data/CONTRIBUTING.md +4 -4
- data/README.md +14 -14
- data/krane.gemspec +4 -4
- data/lib/krane/bindings_parser.rb +2 -2
- data/lib/krane/cli/krane.rb +6 -6
- data/lib/krane/cluster_resource_discovery.rb +3 -3
- data/lib/krane/deploy_task.rb +4 -4
- data/lib/krane/ejson_secret_provisioner.rb +4 -4
- data/lib/krane/global_deploy_task.rb +2 -2
- data/lib/krane/kubectl.rb +10 -1
- data/lib/krane/kubernetes_resource/pod.rb +1 -0
- data/lib/krane/kubernetes_resource/stateful_set.rb +25 -10
- data/lib/krane/resource_cache.rb +1 -1
- data/lib/krane/resource_deployer.rb +7 -6
- data/lib/krane/rollout_conditions.rb +2 -2
- data/lib/krane/version.rb +1 -1
- metadata +15 -15
- data/lib/krane/oj.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a400c15e247a60bf8596665ddf2737abb44c2418358212e689890eb2178956f
|
4
|
+
data.tar.gz: '0386e1417ba00c97add6aa7184176785f82d05de5453140a8806540833c85f46'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8b4c706a3918d6d3b66f098ae03c1e02680d59bef3f8eab34248997bfc11e512206f1b1d1794f50f12965e7a0cffbb2df2293b4639dd28b4b8526db881cf315
|
7
|
+
data.tar.gz: 7d113bfa20d8dec893fa3494ea7f55a9bf89c3a59ca7a461e1076c5fed37c2725b495a96efa5034c18b857819c96f5803045dec444a3c205e70f647b162f8106
|
data/.github/CODEOWNERS
CHANGED
@@ -1 +1 @@
|
|
1
|
-
* @Shopify/
|
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 }}
|
data/.github/workflows/ci.yml
CHANGED
@@ -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/
|
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/
|
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/
|
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/
|
99
|
-
5. Add the new resource to the [prune whitelist](https://github.com/Shopify/krane/blob/
|
100
|
-
6. Add a basic example of the type to the hello-cloud [fixture set](https://github.com/Shopify/krane/tree/
|
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=
|
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/
|
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
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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/
|
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/
|
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/
|
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/
|
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("
|
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.
|
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
|
50
|
-
spec.add_development_dependency("webmock", "~> 3.
|
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 =
|
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
|
64
|
+
rescue MultiJson::ParseError
|
65
65
|
nil
|
66
66
|
end
|
67
67
|
|
data/lib/krane/cli/krane.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
95
|
+
MultiJson.load(raw_json)["items"]
|
96
96
|
else
|
97
97
|
raise FatalKubeAPIError, "Error retrieving CustomResourceDefinition: #{err}"
|
98
98
|
end
|
data/lib/krane/deploy_task.rb
CHANGED
@@ -77,7 +77,7 @@ module Krane
|
|
77
77
|
Hash[before_crs + crs + after_crs]
|
78
78
|
end
|
79
79
|
|
80
|
-
def
|
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
|
-
|
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? ?
|
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
|
-
|
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
|
-
|
121
|
-
rescue
|
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
|
-
|
143
|
-
rescue
|
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
|
-
|
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
|
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 =
|
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)
|
@@ -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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
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
|
-
|
34
|
-
|
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
|
data/lib/krane/resource_cache.rb
CHANGED
@@ -64,7 +64,7 @@ module Krane
|
|
64
64
|
raise KubectlError unless st.success?
|
65
65
|
|
66
66
|
instances = {}
|
67
|
-
|
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:,
|
14
|
+
def initialize(task_config:, prune_allowlist:, global_timeout:, current_sha: nil, selector:, statsd_tags:)
|
15
15
|
@task_config = task_config
|
16
|
-
@
|
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 = @
|
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 && @
|
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
|
-
|
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(
|
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 =
|
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
|
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
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.
|
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-
|
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:
|
106
|
+
name: multi_json
|
107
107
|
requirement: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- - "
|
109
|
+
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: '
|
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: '
|
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.
|
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.
|
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
|
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
|
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.
|
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.
|
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.
|
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