kubernetes-deploy 0.23.0 → 0.24.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.buildkite/pipeline.nightly.yml +8 -8
- data/.buildkite/pipeline.yml +8 -8
- data/.rubocop.yml +0 -9
- data/CHANGELOG.md +17 -0
- data/README.md +93 -4
- data/Rakefile +6 -6
- data/bin/setup +2 -2
- data/exe/kubernetes-deploy +2 -2
- data/exe/kubernetes-render +1 -1
- data/exe/kubernetes-restart +2 -2
- data/exe/kubernetes-run +1 -1
- data/kubernetes-deploy.gemspec +15 -14
- data/lib/kubernetes-deploy.rb +1 -1
- data/lib/kubernetes-deploy/container_logs.rb +1 -1
- data/lib/kubernetes-deploy/deploy_task.rb +24 -19
- data/lib/kubernetes-deploy/ejson_secret_provisioner.rb +2 -2
- data/lib/kubernetes-deploy/kubeclient_builder.rb +1 -1
- data/lib/kubernetes-deploy/kubectl.rb +2 -2
- data/lib/kubernetes-deploy/kubernetes_resource.rb +14 -7
- data/lib/kubernetes-deploy/kubernetes_resource/custom_resource.rb +87 -0
- data/lib/kubernetes-deploy/kubernetes_resource/custom_resource_definition.rb +46 -0
- data/lib/kubernetes-deploy/options_helper.rb +1 -1
- data/lib/kubernetes-deploy/resource_watcher.rb +1 -1
- data/lib/kubernetes-deploy/restart_task.rb +6 -6
- data/lib/kubernetes-deploy/rollout_conditions.rb +103 -0
- data/lib/kubernetes-deploy/runner_task.rb +2 -2
- data/lib/kubernetes-deploy/version.rb +1 -1
- metadata +18 -3
- data/lib/kubernetes-deploy/kubernetes_resource/bucket.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8e6aa3c405f95c085c79e274915275e1d2a225803c4abf21813c11543bdfa8f
|
4
|
+
data.tar.gz: ae315a1ce265d03205bd39972303d54d015a32210b43151c8f5d541377946143
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0111a5ab0e4959ff3e135311ed879f284cb9db70b5a510f0fa0e667385f35ab2c0c0323167f3ac30378d032e2daddeeab2f3afeacf6c36b5f0d3e7a5f5a21754
|
7
|
+
data.tar.gz: 182840922280570f41aa6bff6918b24f8c0a34da631d01fe97c3b078a3ef376346118c0026ef3d4f6f1c96cc1d96e9789f483b00fb0ea35d19044129ea0830e2
|
@@ -4,6 +4,14 @@ shared: &shared
|
|
4
4
|
- exit_status: "*"
|
5
5
|
limit: 1
|
6
6
|
steps:
|
7
|
+
- name: 'Run Test Suite (:kubernetes: 1.13-latest)'
|
8
|
+
<<: *shared
|
9
|
+
command: bin/ci
|
10
|
+
agents:
|
11
|
+
queue: k8s-ci
|
12
|
+
env:
|
13
|
+
LOGGING_LEVEL: 4
|
14
|
+
KUBERNETES_VERSION: v1.13-latest
|
7
15
|
- name: 'Run Test Suite (:kubernetes: 1.12-latest)'
|
8
16
|
<<: *shared
|
9
17
|
command: bin/ci
|
@@ -28,11 +36,3 @@ steps:
|
|
28
36
|
env:
|
29
37
|
LOGGING_LEVEL: 4
|
30
38
|
KUBERNETES_VERSION: v1.10-latest
|
31
|
-
- name: 'Run Test Suite (:kubernetes: 1.9-latest)'
|
32
|
-
<<: *shared
|
33
|
-
command: bin/ci
|
34
|
-
agents:
|
35
|
-
queue: minikube-ci
|
36
|
-
env:
|
37
|
-
LOGGING_LEVEL: 4
|
38
|
-
KUBERNETES_VERSION: v1.9-latest
|
data/.buildkite/pipeline.yml
CHANGED
@@ -4,6 +4,14 @@ shared: &shared
|
|
4
4
|
- exit_status: "*"
|
5
5
|
limit: 1
|
6
6
|
steps:
|
7
|
+
- name: 'Run Test Suite (:kubernetes: 1.13-latest)'
|
8
|
+
<<: *shared
|
9
|
+
command: bin/ci
|
10
|
+
agents:
|
11
|
+
queue: k8s-ci
|
12
|
+
env:
|
13
|
+
LOGGING_LEVEL: 4
|
14
|
+
KUBERNETES_VERSION: v1.13-latest
|
7
15
|
- name: 'Run Test Suite (:kubernetes: 1.12-latest)'
|
8
16
|
<<: *shared
|
9
17
|
command: bin/ci
|
@@ -28,11 +36,3 @@ steps:
|
|
28
36
|
env:
|
29
37
|
LOGGING_LEVEL: 4
|
30
38
|
KUBERNETES_VERSION: v1.10-latest
|
31
|
-
- name: 'Run Test Suite (:kubernetes: 1.9-latest)'
|
32
|
-
<<: *shared
|
33
|
-
command: bin/ci
|
34
|
-
agents:
|
35
|
-
queue: minikube-ci
|
36
|
-
env:
|
37
|
-
LOGGING_LEVEL: 4
|
38
|
-
KUBERNETES_VERSION: v1.9-latest
|
data/.rubocop.yml
CHANGED
@@ -4,15 +4,6 @@ inherit_from:
|
|
4
4
|
AllCops:
|
5
5
|
TargetRubyVersion: 2.3
|
6
6
|
|
7
|
-
Style/TrailingCommaInArrayLiteral:
|
8
|
-
Enabled: false
|
9
|
-
|
10
|
-
Style/TrailingCommaInHashLiteral:
|
11
|
-
Enabled: false
|
12
|
-
|
13
|
-
Style/MethodCallWithArgsParentheses:
|
14
|
-
Enabled: false
|
15
|
-
|
16
7
|
Naming/FileName:
|
17
8
|
Enabled: true
|
18
9
|
Exclude:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
## next
|
2
|
+
|
3
|
+
## 0.24.0
|
4
|
+
|
5
|
+
*Features*
|
6
|
+
- Add support for specifying pass/fail conditions of Custom Resources ([#376](https://github.com/Shopify/kubernetes-deploy/pull/376)).
|
7
|
+
- Add support for custom timeouts for Custom Resources([#376](https://github.com/Shopify/kubernetes-deploy/pull/376))
|
8
|
+
|
9
|
+
*Enhancements*
|
10
|
+
- Officially support Kubernetes 1.13 ([#409](https://github.com/Shopify/kubernetes-deploy/pull/409))
|
11
|
+
|
12
|
+
*Bug fixes*
|
13
|
+
- Fixed bug that caused `NameError: wrong constant name` if custom resources had kind with a lowercase first letter. ([#413](https://github.com/Shopify/kubernetes-deploy/pull/413))
|
14
|
+
|
15
|
+
*Other*
|
16
|
+
- Kubernetes 1.9 is no longer officially supported as of this version
|
17
|
+
|
1
18
|
## 0.23.0
|
2
19
|
|
3
20
|
*Features*
|
data/README.md
CHANGED
@@ -42,6 +42,7 @@ This repo also includes related tools for [running tasks](#kubernetes-run) and [
|
|
42
42
|
* [Customizing behaviour with annotations](#customizing-behaviour-with-annotations)
|
43
43
|
* [Running tasks at the beginning of a deploy](#running-tasks-at-the-beginning-of-a-deploy)
|
44
44
|
* [Deploying Kubernetes secrets (from EJSON)](#deploying-kubernetes-secrets-from-ejson)
|
45
|
+
* [Deploying custom resources](#deploying-custom-resources)
|
45
46
|
|
46
47
|
**KUBERNETES-RESTART**
|
47
48
|
* [Usage](#usage-1)
|
@@ -73,7 +74,7 @@ This repo also includes related tools for [running tasks](#kubernetes-run) and [
|
|
73
74
|
## Prerequisites
|
74
75
|
|
75
76
|
* Ruby 2.3+
|
76
|
-
* Your cluster must be running Kubernetes v1.
|
77
|
+
* Your cluster must be running Kubernetes v1.10.0 or higher<sup>1</sup>
|
77
78
|
* Each app must have a deploy directory containing its Kubernetes templates (see [Templates](#using-templates-and-variables))
|
78
79
|
* You must remove the` kubectl.kubernetes.io/last-applied-configuration` annotation from any resources in the namespace that are not included in your deploy directory. This annotation is added automatically when you create resources with `kubectl apply`. `kubernetes-deploy` will prune any resources that have this annotation and are not in the deploy directory.<sup>2</sup>
|
79
80
|
* Each app managed by `kubernetes-deploy` must have its own exclusive Kubernetes namespace.
|
@@ -92,7 +93,7 @@ offical compatibility chart below.
|
|
92
93
|
|
93
94
|
## Installation
|
94
95
|
|
95
|
-
1. [Install kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-via-curl) (requires v1.
|
96
|
+
1. [Install kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-via-curl) (requires v1.10.0 or higher) and make sure it is available in your $PATH
|
96
97
|
2. Set up your [kubeconfig file](https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/) for access to your cluster(s).
|
97
98
|
3. `gem install kubernetes-deploy`
|
98
99
|
|
@@ -312,7 +313,95 @@ Since their data is only base64 encoded, Kubernetes secrets should not be commit
|
|
312
313
|
}
|
313
314
|
```
|
314
315
|
|
316
|
+
### Deploying custom resources
|
315
317
|
|
318
|
+
By default, kubernetes-deploy does not check the status of custom resources; it simply assumes that they deployed successfully. In order to meaningfully monitor the rollout of custom resources, kubernetes-deploy supports configuring pass/fail conditions using annotations on CustomResourceDefinitions (CRDs).
|
319
|
+
|
320
|
+
>Note:
|
321
|
+
This feature is only available on clusters running Kubernetes 1.11+ since it relies on the `metadata.generation` field being updated when custom resource specs are changed.
|
322
|
+
|
323
|
+
*Requirements:*
|
324
|
+
|
325
|
+
* The custom resource must expose a `status` subresource with an `observedGeneration` field.
|
326
|
+
* The `kubernetes-deploy.shopify.io/instance-rollout-conditions` annotation must be present on the CRD that defines the custom resource.
|
327
|
+
* (optional) The `kubernetes-deploy.shopify.io/instance-timeout` annotation can be added to the CRD that defines the custom resource to override the global default timeout for all instances of that resource. This annotation can use ISO8601 format or unprefixed ISO8601 time components (e.g. '1H', '60S').
|
328
|
+
|
329
|
+
#### Specifying pass/fail conditions
|
330
|
+
|
331
|
+
The presence of a valid `kubernetes-deploy.shopify.io/instance-rollout-conditions` annotation on a CRD will cause kubernetes-deploy to monitor the rollout of all instances of that custom resource. Its value can either be `"true"` (giving you the defaults described in the next section) or a valid JSON string with the following format:
|
332
|
+
```
|
333
|
+
'{
|
334
|
+
"success_conditions": [
|
335
|
+
{ "path": <JsonPath expression>, "value": <target value> }
|
336
|
+
... more success conditions
|
337
|
+
],
|
338
|
+
"failure_conditions": [
|
339
|
+
{ "path": <JsonPath expression>, "value": <target value> }
|
340
|
+
... more failure conditions
|
341
|
+
]
|
342
|
+
}'
|
343
|
+
```
|
344
|
+
|
345
|
+
For all conditions, `path` must be a valid JsonPath expression that points to a field in the custom resource's status. `value` is the value that must be present at `path` in order to fulfill a condition. For a deployment to be successful, _all_ `success_conditions` must be fulfilled. Conversely, the deploy will be marked as failed if _any one of_ `failure_conditions` is fulfilled. `success_conditions` are mandatory, but `failure_conditions` can be omitted (the resource will simply time out if it never reaches a successful state).
|
346
|
+
|
347
|
+
In addition to `path` and `value`, a failure condition can also contain `error_msg_path` or `custom_error_msg`. `error_msg_path` is a JsonPath expression that points to a field you want to surface when a failure condition is fulfilled. For example, a status condition may expose a `message` field that contains a description of the problem it encountered. `custom_error_msg` is a string that can be used if your custom resource doesn't contain sufficient information to warrant using `error_msg_path`. Note that `custom_error_msg` has higher precedence than `error_msg_path` so it will be used in favor of `error_msg_path` when both fields are present.
|
348
|
+
|
349
|
+
**Warning:**
|
350
|
+
|
351
|
+
You **must** ensure that your custom resource controller sets `.status.observedGeneration` to match the observed `.metadata.generation` of the monitored resource once its sync is complete. If this does not happen, kubernetes-deploy will not check success or failure conditions and the deploy will time out.
|
352
|
+
|
353
|
+
#### Example
|
354
|
+
|
355
|
+
As an example, the following is the default configuration that will be used if you set `kubernetes-deploy.shopify.io/instance-rollout-conditions: "true"` on the CRD that defines the custom resources you wish to monitor:
|
356
|
+
|
357
|
+
```
|
358
|
+
'{
|
359
|
+
"success_conditions": [
|
360
|
+
{
|
361
|
+
"path": "$.status.conditions[?(@.type == \"Ready\")].status",
|
362
|
+
"value": "True",
|
363
|
+
},
|
364
|
+
],
|
365
|
+
"failure_conditions": [
|
366
|
+
{
|
367
|
+
"path": '$.status.conditions[?(@.type == \"Failed\")].status',
|
368
|
+
"value": "True",
|
369
|
+
"error_msg_path": '$.status.conditions[?(@.type == \"Failed\")].message',
|
370
|
+
},
|
371
|
+
],
|
372
|
+
}'
|
373
|
+
```
|
374
|
+
|
375
|
+
The paths defined here are based on the [typical status properties](https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties) as defined by the Kubernetes community. It expects the `status` subresource to contain a `conditions` array whose entries minimally specify `type`, `status`, and `message` fields.
|
376
|
+
|
377
|
+
You can see how these conditions relate to the following resource:
|
378
|
+
|
379
|
+
```
|
380
|
+
apiVersion: stable.shopify.io/v1
|
381
|
+
kind: Example
|
382
|
+
metadata:
|
383
|
+
generation: 2
|
384
|
+
name: example
|
385
|
+
namespace: namespace
|
386
|
+
spec:
|
387
|
+
...
|
388
|
+
status:
|
389
|
+
observedGeneration: 2
|
390
|
+
conditions:
|
391
|
+
- type: "Ready"
|
392
|
+
status: "False"
|
393
|
+
reason: "exampleNotReady"
|
394
|
+
message: "resource is not ready"
|
395
|
+
- type: "Failed"
|
396
|
+
status: "True"
|
397
|
+
reason: "exampleFailed"
|
398
|
+
message: "resource is failed"
|
399
|
+
```
|
400
|
+
|
401
|
+
- `observedGeneration == metadata.generation`, so kubernetes-deploy will check this resource's success and failure conditions.
|
402
|
+
- Since `$.status.conditions[?(@.type == "Ready")].status == "False"`, the resource is not considered successful yet.
|
403
|
+
- `$.status.conditions[?(@.type == "Failed")].status == "True"` means that a failure condition has been fulfilled and the resource is considered failed.
|
404
|
+
- Since `error_msg_path` is specified, kubernetes-deploy will log the contents of `$.status.conditions[?(@.type == "Failed")].message`, which in this case is: `resource is failed`.
|
316
405
|
|
317
406
|
# kubernetes-restart
|
318
407
|
|
@@ -354,7 +443,7 @@ With this done, you can use the following command to restart all of them:
|
|
354
443
|
|
355
444
|
## Prerequisites
|
356
445
|
|
357
|
-
* You've already deployed a [`PodTemplate`](https://kubernetes.io/docs/
|
446
|
+
* You've already deployed a [`PodTemplate`](https://v1-10.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/#podtemplate-v1-core) object with field `template` containing a `Pod` specification that does not include the `apiVersion` or `kind` parameters. An example is provided in this repo in `test/fixtures/hello-cloud/template-runner.yml`.
|
358
447
|
* The `Pod` specification in that template has a container named `task-runner`.
|
359
448
|
|
360
449
|
Based on this specification `kubernetes-run` will create a new pod with the entrypoint of the `task-runner ` container overridden with the supplied arguments.
|
@@ -411,7 +500,7 @@ kubernetes-render --template-dir=./path/to/template/dir this-template.yaml.erb t
|
|
411
500
|
|
412
501
|
If you work for Shopify, just run `dev up`, but otherwise:
|
413
502
|
|
414
|
-
1. [Install kubectl version 1.
|
503
|
+
1. [Install kubectl version 1.10.0 or higher](https://kubernetes.io/docs/user-guide/prereqs/) and make sure it is in your path
|
415
504
|
2. [Install minikube](https://kubernetes.io/docs/getting-started-guides/minikube/#installation) (required to run the test suite)
|
416
505
|
3. Check out the repo
|
417
506
|
4. Run `bin/setup` to install dependencies
|
data/Rakefile
CHANGED
@@ -2,28 +2,28 @@
|
|
2
2
|
require "bundler/gem_tasks"
|
3
3
|
require "rake/testtask"
|
4
4
|
|
5
|
-
desc
|
5
|
+
desc("Run integration tests that can be run in parallel")
|
6
6
|
Rake::TestTask.new(:integration_test) do |t|
|
7
7
|
t.libs << "test"
|
8
8
|
t.libs << "lib"
|
9
9
|
t.test_files = FileList['test/integration/**/*_test.rb']
|
10
10
|
end
|
11
11
|
|
12
|
-
desc
|
12
|
+
desc("Run integration tests that CANNOT be run in parallel")
|
13
13
|
Rake::TestTask.new(:serial_integration_test) do |t|
|
14
14
|
t.libs << "test"
|
15
15
|
t.libs << "lib"
|
16
16
|
t.test_files = FileList['test/integration-serial/**/*_test.rb']
|
17
17
|
end
|
18
18
|
|
19
|
-
desc
|
19
|
+
desc("Run unit tests")
|
20
20
|
Rake::TestTask.new(:unit_test) do |t|
|
21
21
|
t.libs << "test"
|
22
22
|
t.libs << "lib"
|
23
23
|
t.test_files = FileList['test/unit/**/*_test.rb']
|
24
24
|
end
|
25
25
|
|
26
|
-
desc
|
27
|
-
task
|
26
|
+
desc("Run all tests")
|
27
|
+
task(test: %w(unit_test serial_integration_test integration_test))
|
28
28
|
|
29
|
-
task
|
29
|
+
task(default: :test)
|
data/bin/setup
CHANGED
@@ -9,8 +9,8 @@ if [ ! -x "$(which minikube)" ]; then
|
|
9
9
|
fi
|
10
10
|
|
11
11
|
if [ ! -x "$(which kubectl)" ]; then
|
12
|
-
echo -e "\n\033[0;33mPlease install kubectl version 1.
|
12
|
+
echo -e "\n\033[0;33mPlease install kubectl version 1.10.0 or higher:\nhttps://kubernetes.io/docs/user-guide/prereqs/\033[0m"
|
13
13
|
else
|
14
14
|
KUBECTL_VERSION=$(kubectl version --short --client | grep -oe "v[[:digit:]\.]\+")
|
15
|
-
echo -e "\n\033[0;32mKubectl version $KUBECTL_VERSION is already installed. This gem requires version v1.
|
15
|
+
echo -e "\n\033[0;32mKubectl version $KUBECTL_VERSION is already installed. This gem requires version v1.10.0 or greater.\033[0m"
|
16
16
|
fi
|
data/exe/kubernetes-deploy
CHANGED
data/exe/kubernetes-render
CHANGED
data/exe/kubernetes-restart
CHANGED
@@ -23,7 +23,7 @@ restart = KubernetesDeploy::RestartTask.new(namespace: namespace, context: conte
|
|
23
23
|
begin
|
24
24
|
restart.perform!(raw_deployments)
|
25
25
|
rescue KubernetesDeploy::DeploymentTimeoutError
|
26
|
-
exit
|
26
|
+
exit(70)
|
27
27
|
rescue KubernetesDeploy::FatalDeploymentError
|
28
|
-
exit
|
28
|
+
exit(1)
|
29
29
|
end
|
data/exe/kubernetes-run
CHANGED
data/kubernetes-deploy.gemspec
CHANGED
@@ -23,19 +23,20 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.require_paths = %w(lib)
|
24
24
|
|
25
25
|
spec.required_ruby_version = '>= 2.3.0'
|
26
|
-
spec.add_dependency
|
27
|
-
spec.add_dependency
|
28
|
-
spec.add_dependency
|
29
|
-
spec.add_dependency
|
30
|
-
spec.add_dependency
|
31
|
-
spec.add_dependency
|
32
|
-
spec.add_dependency
|
33
|
-
spec.add_dependency
|
26
|
+
spec.add_dependency("activesupport", ">= 5.0")
|
27
|
+
spec.add_dependency("kubeclient", "~> 3.0")
|
28
|
+
spec.add_dependency("googleauth", "~> 0.6.6") # https://github.com/google/google-auth-library-ruby/issues/153
|
29
|
+
spec.add_dependency("ejson", "~> 1.0")
|
30
|
+
spec.add_dependency("colorize", "~> 0.8")
|
31
|
+
spec.add_dependency("statsd-instrument", '~> 2.3', '>= 2.3.2')
|
32
|
+
spec.add_dependency("oj", "~> 3.7")
|
33
|
+
spec.add_dependency("concurrent-ruby", "~> 1.1")
|
34
|
+
spec.add_dependency("jsonpath", "~> 0.9.6")
|
34
35
|
|
35
|
-
spec.add_development_dependency
|
36
|
-
spec.add_development_dependency
|
37
|
-
spec.add_development_dependency
|
38
|
-
spec.add_development_dependency
|
39
|
-
spec.add_development_dependency
|
40
|
-
spec.add_development_dependency
|
36
|
+
spec.add_development_dependency("bundler")
|
37
|
+
spec.add_development_dependency("rake", "~> 10.0")
|
38
|
+
spec.add_development_dependency("minitest", "~> 5.0")
|
39
|
+
spec.add_development_dependency("minitest-stub-const", "~> 0.6")
|
40
|
+
spec.add_development_dependency("webmock", "~> 3.0")
|
41
|
+
spec.add_development_dependency("mocha", "~> 1.5")
|
41
42
|
end
|
data/lib/kubernetes-deploy.rb
CHANGED
@@ -6,6 +6,7 @@ require 'tempfile'
|
|
6
6
|
require 'fileutils'
|
7
7
|
require 'kubernetes-deploy/kubernetes_resource'
|
8
8
|
%w(
|
9
|
+
custom_resource
|
9
10
|
cloudsql
|
10
11
|
config_map
|
11
12
|
deployment
|
@@ -24,7 +25,6 @@ require 'kubernetes-deploy/kubernetes_resource'
|
|
24
25
|
elasticsearch
|
25
26
|
statefulservice
|
26
27
|
topic
|
27
|
-
bucket
|
28
28
|
stateful_set
|
29
29
|
cron_job
|
30
30
|
job
|
@@ -46,19 +46,6 @@ module KubernetesDeploy
|
|
46
46
|
include KubeclientBuilder
|
47
47
|
extend KubernetesDeploy::StatsD::MeasureMethods
|
48
48
|
|
49
|
-
PREDEPLOY_SEQUENCE = %w(
|
50
|
-
ResourceQuota
|
51
|
-
Cloudsql
|
52
|
-
Redis
|
53
|
-
Memcached
|
54
|
-
ConfigMap
|
55
|
-
PersistentVolumeClaim
|
56
|
-
ServiceAccount
|
57
|
-
Role
|
58
|
-
RoleBinding
|
59
|
-
Pod
|
60
|
-
)
|
61
|
-
|
62
49
|
PROTECTED_NAMESPACES = %w(
|
63
50
|
default
|
64
51
|
kube-system
|
@@ -73,6 +60,22 @@ module KubernetesDeploy
|
|
73
60
|
# extensions/v1beta1/ReplicaSet -- managed by deployments
|
74
61
|
# core/v1/Secret -- should not committed / managed by shipit
|
75
62
|
|
63
|
+
def predeploy_sequence
|
64
|
+
before_crs = %w(
|
65
|
+
ResourceQuota
|
66
|
+
)
|
67
|
+
after_crs = %w(
|
68
|
+
ConfigMap
|
69
|
+
PersistentVolumeClaim
|
70
|
+
ServiceAccount
|
71
|
+
Role
|
72
|
+
RoleBinding
|
73
|
+
Pod
|
74
|
+
)
|
75
|
+
|
76
|
+
before_crs + cluster_resource_discoverer.crds.map(&:kind) + after_crs
|
77
|
+
end
|
78
|
+
|
76
79
|
def prune_whitelist
|
77
80
|
wl = %w(
|
78
81
|
core/v1/ConfigMap
|
@@ -194,11 +197,11 @@ module KubernetesDeploy
|
|
194
197
|
end
|
195
198
|
|
196
199
|
def deploy_has_priority_resources?(resources)
|
197
|
-
resources.any? { |r|
|
200
|
+
resources.any? { |r| predeploy_sequence.include?(r.type) }
|
198
201
|
end
|
199
202
|
|
200
203
|
def predeploy_priority_resources(resource_list)
|
201
|
-
|
204
|
+
predeploy_sequence.each do |resource_type|
|
202
205
|
matching_resources = resource_list.select { |r| r.type == resource_type }
|
203
206
|
next if matching_resources.empty?
|
204
207
|
deploy_resources(matching_resources, verify: true, record_summary: false)
|
@@ -254,14 +257,16 @@ module KubernetesDeploy
|
|
254
257
|
|
255
258
|
def discover_resources
|
256
259
|
resources = []
|
260
|
+
crds = cluster_resource_discoverer.crds.group_by(&:kind)
|
257
261
|
@logger.info("Discovering templates:")
|
258
262
|
|
259
263
|
TemplateDiscovery.new(@template_dir).templates.each do |filename|
|
260
264
|
split_templates(filename) do |r_def|
|
261
|
-
|
262
|
-
|
265
|
+
crd = crds[r_def["kind"]]&.first
|
266
|
+
r = KubernetesResource.build(namespace: @namespace, context: @context, logger: @logger, definition: r_def,
|
267
|
+
statsd_tags: @namespace_tags, crd: crd)
|
263
268
|
resources << r
|
264
|
-
@logger.info
|
269
|
+
@logger.info(" - #{r.id}")
|
265
270
|
end
|
266
271
|
end
|
267
272
|
if (global = resources.select(&:global?).presence)
|
@@ -145,9 +145,9 @@ module KubernetesDeploy
|
|
145
145
|
"name" => secret_name,
|
146
146
|
"labels" => { "name" => secret_name },
|
147
147
|
"namespace" => @namespace,
|
148
|
-
"annotations" => { MANAGEMENT_ANNOTATION => "true" }
|
148
|
+
"annotations" => { MANAGEMENT_ANNOTATION => "true" },
|
149
149
|
},
|
150
|
-
"data" => encoded_data
|
150
|
+
"data" => encoded_data,
|
151
151
|
}
|
152
152
|
secret.to_yaml
|
153
153
|
end
|
@@ -100,7 +100,7 @@ module KubernetesDeploy
|
|
100
100
|
auth_options: kube_context.auth_options,
|
101
101
|
timeouts: {
|
102
102
|
open: KubernetesDeploy::Kubectl::DEFAULT_TIMEOUT,
|
103
|
-
read: KubernetesDeploy::Kubectl::DEFAULT_TIMEOUT
|
103
|
+
read: KubernetesDeploy::Kubectl::DEFAULT_TIMEOUT,
|
104
104
|
}
|
105
105
|
)
|
106
106
|
client.discover
|
@@ -30,7 +30,7 @@ module KubernetesDeploy
|
|
30
30
|
out, err, st = nil
|
31
31
|
|
32
32
|
(1..attempts).to_a.each do |attempt|
|
33
|
-
@logger.debug
|
33
|
+
@logger.debug("Running command (attempt #{attempt}): #{args.join(' ')}")
|
34
34
|
out, err, st = Open3.capture3(*args)
|
35
35
|
@logger.debug("Kubectl out: " + out.gsub(/\s+/, ' ')) unless output_is_sensitive?
|
36
36
|
|
@@ -47,7 +47,7 @@ module KubernetesDeploy
|
|
47
47
|
@logger.debug("Kubectl err: #{err}") unless output_is_sensitive?
|
48
48
|
StatsD.increment('kubectl.error', 1, tags: { context: @context, namespace: @namespace, cmd: args[1] })
|
49
49
|
end
|
50
|
-
sleep
|
50
|
+
sleep(retry_delay(attempt)) unless attempt == attempts
|
51
51
|
end
|
52
52
|
|
53
53
|
[out.chomp, err.chomp, st]
|
@@ -31,14 +31,21 @@ module KubernetesDeploy
|
|
31
31
|
TIMEOUT_OVERRIDE_ANNOTATION = "kubernetes-deploy.shopify.io/timeout-override"
|
32
32
|
|
33
33
|
class << self
|
34
|
-
def build(namespace:, context:, definition:, logger:, statsd_tags:)
|
34
|
+
def build(namespace:, context:, definition:, logger:, statsd_tags:, crd: nil)
|
35
35
|
opts = { namespace: namespace, context: context, definition: definition, logger: logger,
|
36
36
|
statsd_tags: statsd_tags }
|
37
37
|
if definition["kind"].blank?
|
38
38
|
raise InvalidTemplateError.new("Template missing 'Kind'", content: definition.to_yaml)
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
end
|
40
|
+
begin
|
41
|
+
if KubernetesDeploy.const_defined?(definition["kind"])
|
42
|
+
klass = KubernetesDeploy.const_get(definition["kind"])
|
43
|
+
return klass.new(**opts)
|
44
|
+
end
|
45
|
+
rescue NameError
|
46
|
+
end
|
47
|
+
if crd
|
48
|
+
CustomResource.new(crd: crd, **opts)
|
42
49
|
else
|
43
50
|
inst = new(**opts)
|
44
51
|
inst.type = definition["kind"]
|
@@ -162,13 +169,13 @@ module KubernetesDeploy
|
|
162
169
|
|
163
170
|
def current_generation
|
164
171
|
return -1 unless exists? # must be different default than observed_generation
|
165
|
-
@instance_data
|
172
|
+
@instance_data.dig("metadata", "generation")
|
166
173
|
end
|
167
174
|
|
168
175
|
def observed_generation
|
169
176
|
return -2 unless exists?
|
170
177
|
# populating this is a best practice, but not all controllers actually do it
|
171
|
-
@instance_data
|
178
|
+
@instance_data.dig('status', 'observedGeneration')
|
172
179
|
end
|
173
180
|
|
174
181
|
def status
|
@@ -319,7 +326,7 @@ module KubernetesDeploy
|
|
319
326
|
'(ne .reason "SuccessfulCreate")',
|
320
327
|
'(ne .reason "Scheduled")',
|
321
328
|
'(ne .reason "Pulling")',
|
322
|
-
'(ne .reason "Pulled")'
|
329
|
+
'(ne .reason "Pulled")',
|
323
330
|
]
|
324
331
|
condition_start = "{{if and #{and_conditions.join(' ')}}}"
|
325
332
|
field_part = FIELDS.map { |f| "{{#{f}}}" }.join(%({{print "#{FIELD_SEPARATOR}"}}))
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'jsonpath'
|
3
|
+
|
4
|
+
module KubernetesDeploy
|
5
|
+
class CustomResource < KubernetesResource
|
6
|
+
TIMEOUT_MESSAGE_DIFFERENT_GENERATIONS = <<~MSG
|
7
|
+
This resource's status could not be used to determine rollout success because it is not up-to-date
|
8
|
+
(.metadata.generation != .status.observedGeneration).
|
9
|
+
MSG
|
10
|
+
|
11
|
+
def initialize(namespace:, context:, definition:, logger:, statsd_tags: [], crd:)
|
12
|
+
super(namespace: namespace, context: context, definition: definition,
|
13
|
+
logger: logger, statsd_tags: statsd_tags)
|
14
|
+
@crd = crd
|
15
|
+
end
|
16
|
+
|
17
|
+
def timeout
|
18
|
+
timeout_override || @crd.timeout_for_instance || TIMEOUT
|
19
|
+
end
|
20
|
+
|
21
|
+
def deploy_succeeded?
|
22
|
+
return super unless rollout_conditions
|
23
|
+
return false unless observed_generation == current_generation
|
24
|
+
|
25
|
+
rollout_conditions.rollout_successful?(@instance_data)
|
26
|
+
end
|
27
|
+
|
28
|
+
def deploy_failed?
|
29
|
+
return super unless rollout_conditions
|
30
|
+
return false unless observed_generation == current_generation
|
31
|
+
|
32
|
+
rollout_conditions.rollout_failed?(@instance_data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure_message
|
36
|
+
return super unless rollout_conditions
|
37
|
+
messages = rollout_conditions.failure_messages(@instance_data)
|
38
|
+
messages.join("\n") if messages.present?
|
39
|
+
end
|
40
|
+
|
41
|
+
def timeout_message
|
42
|
+
if rollout_conditions && current_generation != observed_generation
|
43
|
+
TIMEOUT_MESSAGE_DIFFERENT_GENERATIONS
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def status
|
50
|
+
if !exists? || rollout_conditions.nil?
|
51
|
+
super
|
52
|
+
elsif deploy_succeeded?
|
53
|
+
"Healthy"
|
54
|
+
elsif deploy_failed?
|
55
|
+
"Unhealthy"
|
56
|
+
else
|
57
|
+
"Unknown"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def type
|
62
|
+
kind
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate_definition(kubectl)
|
66
|
+
super
|
67
|
+
|
68
|
+
@crd.validate_rollout_conditions
|
69
|
+
rescue RolloutConditionsError => e
|
70
|
+
@validation_errors << "The CRD that specifies this resource is using invalid rollout conditions. " \
|
71
|
+
"Kubernetes-deploy will not be able to continue until those rollout conditions are fixed.\n" \
|
72
|
+
"Rollout conditions can be found on the CRD that defines this resource (#{@crd.name}), " \
|
73
|
+
"under the annotation #{CustomResourceDefinition::ROLLOUT_CONDITIONS_ANNOTATION}.\n" \
|
74
|
+
"Validation failed with: #{e}"
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def kind
|
80
|
+
@definition["kind"]
|
81
|
+
end
|
82
|
+
|
83
|
+
def rollout_conditions
|
84
|
+
@crd.rollout_conditions
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -1,7 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'kubernetes-deploy/rollout_conditions'
|
3
|
+
|
2
4
|
module KubernetesDeploy
|
3
5
|
class CustomResourceDefinition < KubernetesResource
|
4
6
|
TIMEOUT = 2.minutes
|
7
|
+
ROLLOUT_CONDITIONS_ANNOTATION = "kubernetes-deploy.shopify.io/instance-rollout-conditions"
|
8
|
+
TIMEOUT_FOR_INSTANCE_ANNOTATION = "kubernetes-deploy.shopify.io/instance-timeout"
|
5
9
|
GLOBAL = true
|
6
10
|
|
7
11
|
def deploy_succeeded?
|
@@ -16,6 +20,13 @@ module KubernetesDeploy
|
|
16
20
|
"The names this CRD is attempting to register were neither accepted nor rejected in time"
|
17
21
|
end
|
18
22
|
|
23
|
+
def timeout_for_instance
|
24
|
+
timeout = @definition.dig("metadata", "annotations", TIMEOUT_FOR_INSTANCE_ANNOTATION)
|
25
|
+
DurationParser.new(timeout).parse!.to_i
|
26
|
+
rescue DurationParser::ParsingError
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
19
30
|
def status
|
20
31
|
if !exists?
|
21
32
|
super
|
@@ -36,11 +47,42 @@ module KubernetesDeploy
|
|
36
47
|
@definition.dig("spec", "names", "kind")
|
37
48
|
end
|
38
49
|
|
50
|
+
def name
|
51
|
+
@definition.dig("metadata", "name")
|
52
|
+
end
|
53
|
+
|
39
54
|
def prunable?
|
40
55
|
prunable = @definition.dig("metadata", "annotations", "kubernetes-deploy.shopify.io/prunable")
|
41
56
|
prunable == "true"
|
42
57
|
end
|
43
58
|
|
59
|
+
def rollout_conditions
|
60
|
+
return @rollout_conditions if defined?(@rollout_conditions)
|
61
|
+
|
62
|
+
@rollout_conditions = if rollout_conditions_annotation
|
63
|
+
RolloutConditions.from_annotation(rollout_conditions_annotation)
|
64
|
+
end
|
65
|
+
rescue RolloutConditionsError
|
66
|
+
@rollout_conditions = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_definition(_)
|
70
|
+
super
|
71
|
+
|
72
|
+
validate_rollout_conditions
|
73
|
+
rescue RolloutConditionsError => e
|
74
|
+
@validation_errors << "Annotation #{ROLLOUT_CONDITIONS_ANNOTATION} on #{name} is invalid: #{e}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_rollout_conditions
|
78
|
+
if rollout_conditions_annotation && @rollout_conditions_validated.nil?
|
79
|
+
conditions = RolloutConditions.from_annotation(rollout_conditions_annotation)
|
80
|
+
conditions.validate!
|
81
|
+
end
|
82
|
+
|
83
|
+
@rollout_conditions_validated = true
|
84
|
+
end
|
85
|
+
|
44
86
|
private
|
45
87
|
|
46
88
|
def names_accepted_condition
|
@@ -51,5 +93,9 @@ module KubernetesDeploy
|
|
51
93
|
def names_accepted_status
|
52
94
|
names_accepted_condition["status"]
|
53
95
|
end
|
96
|
+
|
97
|
+
def rollout_conditions_annotation
|
98
|
+
@definition.dig("metadata", "annotations", ROLLOUT_CONDITIONS_ANNOTATION)
|
99
|
+
end
|
54
100
|
end
|
55
101
|
end
|
@@ -132,7 +132,7 @@ module KubernetesDeploy
|
|
132
132
|
deployments.each do |record|
|
133
133
|
begin
|
134
134
|
patch_deployment_with_restart(record)
|
135
|
-
@logger.info
|
135
|
+
@logger.info("Triggered `#{record.metadata.name}` restart")
|
136
136
|
rescue Kubeclient::ResourceNotFoundError, Kubeclient::HttpError => e
|
137
137
|
raise RestartAPIError.new(record.metadata.name, e.message)
|
138
138
|
end
|
@@ -164,12 +164,12 @@ module KubernetesDeploy
|
|
164
164
|
containers: containers.map do |container|
|
165
165
|
{
|
166
166
|
name: container.name,
|
167
|
-
env: [{ name: "RESTARTED_AT", value: Time.now.to_i.to_s }]
|
167
|
+
env: [{ name: "RESTARTED_AT", value: Time.now.to_i.to_s }],
|
168
168
|
}
|
169
|
-
end
|
170
|
-
}
|
171
|
-
}
|
172
|
-
}
|
169
|
+
end,
|
170
|
+
},
|
171
|
+
},
|
172
|
+
},
|
173
173
|
}
|
174
174
|
end
|
175
175
|
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module KubernetesDeploy
|
3
|
+
class RolloutConditionsError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class RolloutConditions
|
7
|
+
VALID_FAILURE_CONDITION_KEYS = [:path, :value, :error_msg_path, :custom_error_msg]
|
8
|
+
VALID_SUCCESS_CONDITION_KEYS = [:path, :value]
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def from_annotation(conditions_string)
|
12
|
+
return new(default_conditions) if conditions_string.downcase.strip == "true"
|
13
|
+
|
14
|
+
conditions = JSON.parse(conditions_string).slice('success_conditions', 'failure_conditions')
|
15
|
+
conditions.deep_symbolize_keys!
|
16
|
+
|
17
|
+
# Create JsonPath objects
|
18
|
+
conditions[:success_conditions]&.each do |query|
|
19
|
+
query.slice!(*VALID_SUCCESS_CONDITION_KEYS)
|
20
|
+
query[:path] = JsonPath.new(query[:path]) if query.key?(:path)
|
21
|
+
end
|
22
|
+
conditions[:failure_conditions]&.each do |query|
|
23
|
+
query.slice!(*VALID_FAILURE_CONDITION_KEYS)
|
24
|
+
query[:path] = JsonPath.new(query[:path]) if query.key?(:path)
|
25
|
+
query[:error_msg_path] = JsonPath.new(query[:error_msg_path]) if query.key?(:error_msg_path)
|
26
|
+
end
|
27
|
+
|
28
|
+
new(conditions)
|
29
|
+
rescue JSON::ParserError => e
|
30
|
+
raise RolloutConditionsError, "Rollout conditions are not valid JSON: #{e}"
|
31
|
+
rescue StandardError => e
|
32
|
+
raise RolloutConditionsError,
|
33
|
+
"Error parsing rollout conditions. " \
|
34
|
+
"This is most likely caused by an invalid JsonPath expression. Failed with: #{e}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_conditions
|
38
|
+
{
|
39
|
+
success_conditions: [
|
40
|
+
{
|
41
|
+
path: JsonPath.new('$.status.conditions[?(@.type == "Ready")].status'),
|
42
|
+
value: "True",
|
43
|
+
},
|
44
|
+
],
|
45
|
+
failure_conditions: [
|
46
|
+
{
|
47
|
+
path: JsonPath.new('$.status.conditions[?(@.type == "Failed")].status'),
|
48
|
+
value: "True",
|
49
|
+
error_msg_path: JsonPath.new('$.status.conditions[?(@.type == "Failed")].message'),
|
50
|
+
},
|
51
|
+
],
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(conditions)
|
57
|
+
@success_conditions = conditions.fetch(:success_conditions, [])
|
58
|
+
@failure_conditions = conditions.fetch(:failure_conditions, [])
|
59
|
+
end
|
60
|
+
|
61
|
+
def rollout_successful?(instance_data)
|
62
|
+
@success_conditions.all? do |query|
|
63
|
+
query[:path].first(instance_data) == query[:value]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def rollout_failed?(instance_data)
|
68
|
+
@failure_conditions.any? do |query|
|
69
|
+
query[:path].first(instance_data) == query[:value]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def failure_messages(instance_data)
|
74
|
+
@failure_conditions.map do |query|
|
75
|
+
next unless query[:path].first(instance_data) == query[:value]
|
76
|
+
query[:custom_error_msg].presence || query[:error_msg_path]&.first(instance_data)
|
77
|
+
end.compact
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate!
|
81
|
+
errors = validate_conditions(@success_conditions, 'success_conditions')
|
82
|
+
errors += validate_conditions(@failure_conditions, 'failure_conditions', required: false)
|
83
|
+
raise RolloutConditionsError, errors.join(", ") unless errors.empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def validate_conditions(conditions, source_key, required: true)
|
89
|
+
return [] unless conditions.present? || required
|
90
|
+
errors = []
|
91
|
+
errors << "#{source_key} should be Array but found #{conditions.class}" unless conditions.is_a?(Array)
|
92
|
+
return errors if errors.present?
|
93
|
+
errors << "#{source_key} must contain at least one entry" if conditions.empty?
|
94
|
+
return errors if errors.present?
|
95
|
+
|
96
|
+
conditions.each do |query|
|
97
|
+
missing = [:path, :value].reject { |k| query.key?(k) }
|
98
|
+
errors << "Missing required key(s) for #{source_key.singularize}: #{missing}" if missing.present?
|
99
|
+
end
|
100
|
+
errors
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -59,7 +59,7 @@ module KubernetesDeploy
|
|
59
59
|
private
|
60
60
|
|
61
61
|
def create_pod(pod)
|
62
|
-
@logger.info
|
62
|
+
@logger.info("Creating pod '#{pod.name}'")
|
63
63
|
pod.deploy_started_at = Time.now.utc
|
64
64
|
kubeclient.create_pod(pod.to_kubeclient_resource)
|
65
65
|
@pod_name = pod.name
|
@@ -121,7 +121,7 @@ module KubernetesDeploy
|
|
121
121
|
|
122
122
|
begin
|
123
123
|
kubeclient.get_namespace(@namespace) if @namespace.present?
|
124
|
-
@logger.info
|
124
|
+
@logger.info("Using namespace '#{@namespace}' in context '#{@context}'")
|
125
125
|
rescue KubeException => e
|
126
126
|
msg = e.error_code == 404 ? "Namespace was not found" : "Could not connect to kubernetes cluster"
|
127
127
|
errors << msg
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kubernetes-deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.24.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katrina Verey
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-01-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -129,6 +129,20 @@ dependencies:
|
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '1.1'
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: jsonpath
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.9.6
|
139
|
+
type: :runtime
|
140
|
+
prerelease: false
|
141
|
+
version_requirements: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.9.6
|
132
146
|
- !ruby/object:Gem::Dependency
|
133
147
|
name: bundler
|
134
148
|
requirement: !ruby/object:Gem::Requirement
|
@@ -261,10 +275,10 @@ files:
|
|
261
275
|
- lib/kubernetes-deploy/kubeclient_builder/google_friendly_config.rb
|
262
276
|
- lib/kubernetes-deploy/kubectl.rb
|
263
277
|
- lib/kubernetes-deploy/kubernetes_resource.rb
|
264
|
-
- lib/kubernetes-deploy/kubernetes_resource/bucket.rb
|
265
278
|
- lib/kubernetes-deploy/kubernetes_resource/cloudsql.rb
|
266
279
|
- lib/kubernetes-deploy/kubernetes_resource/config_map.rb
|
267
280
|
- lib/kubernetes-deploy/kubernetes_resource/cron_job.rb
|
281
|
+
- lib/kubernetes-deploy/kubernetes_resource/custom_resource.rb
|
268
282
|
- lib/kubernetes-deploy/kubernetes_resource/custom_resource_definition.rb
|
269
283
|
- lib/kubernetes-deploy/kubernetes_resource/daemon_set.rb
|
270
284
|
- lib/kubernetes-deploy/kubernetes_resource/deployment.rb
|
@@ -296,6 +310,7 @@ files:
|
|
296
310
|
- lib/kubernetes-deploy/resource_cache.rb
|
297
311
|
- lib/kubernetes-deploy/resource_watcher.rb
|
298
312
|
- lib/kubernetes-deploy/restart_task.rb
|
313
|
+
- lib/kubernetes-deploy/rollout_conditions.rb
|
299
314
|
- lib/kubernetes-deploy/runner_task.rb
|
300
315
|
- lib/kubernetes-deploy/statsd.rb
|
301
316
|
- lib/kubernetes-deploy/template_discovery.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module KubernetesDeploy
|
3
|
-
class Bucket < KubernetesResource
|
4
|
-
def deploy_succeeded?
|
5
|
-
return false unless deploy_started?
|
6
|
-
|
7
|
-
unless @success_assumption_warning_shown
|
8
|
-
@logger.warn("Don't know how to monitor resources of type #{type}. Assuming #{id} deployed successfully.")
|
9
|
-
@success_assumption_warning_shown = true
|
10
|
-
end
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
14
|
-
def status
|
15
|
-
exists? ? "Available" : "Unknown"
|
16
|
-
end
|
17
|
-
|
18
|
-
def deploy_failed?
|
19
|
-
false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|