kubernetes-deploy 0.26.3 → 0.26.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +11 -0
- data/CONTRIBUTING.md +8 -10
- data/README.md +2 -0
- data/dev.yml +4 -0
- data/exe/kubernetes-render +1 -1
- data/kubernetes-deploy.gemspec +1 -1
- data/lib/kubernetes-deploy/deferred_summary_logging.rb +1 -1
- data/lib/kubernetes-deploy/deploy_task.rb +10 -4
- data/lib/kubernetes-deploy/ejson_secret_provisioner.rb +5 -1
- data/lib/kubernetes-deploy/kubernetes_resource.rb +26 -15
- data/lib/kubernetes-deploy/kubernetes_resource/cloudsql.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/memcached.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/pod.rb +2 -3
- data/lib/kubernetes-deploy/kubernetes_resource/redis.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/secret.rb +1 -1
- data/lib/kubernetes-deploy/resource_cache.rb +1 -1
- data/lib/kubernetes-deploy/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a537ded5641b9cb4b9813594e6da9d7ea06876721b26ce4785e48f0b933536cf
|
4
|
+
data.tar.gz: 8ee185bc26198298d5ed8c18aba4736a67bc46bd2526a72d71b74c988ac9e657
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33f35406225136f90fa99219f5545d9052e2d323055f87d0d42c81640549cda6f18c0748d661ae4ba4c4ab7a1bcb0e7c717e6c8081ded664849befd2bf571d3c
|
7
|
+
data.tar.gz: 3d3e78256ad83ea456f9a92106c81b03c0212fc3d0940cdfbb990a45214f7250af1110c4f3231dde8b828ab4113b68c3ce5dfc28d675a001d19eea686b2bb9ca
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## next
|
2
2
|
|
3
|
+
## 0.26.4
|
4
|
+
|
5
|
+
*Bug fixes*
|
6
|
+
- Adds several additional safeguards against the content of Secret resources being logged. [#474](https://github.com/Shopify/kubernetes-deploy/pull/474)
|
7
|
+
|
8
|
+
*Enhancements*
|
9
|
+
- Improves scalability by removing a check that caused recoverable registry problems to fail deploys. [#477](https://github.com/Shopify/kubernetes-deploy/pull/477)
|
10
|
+
|
11
|
+
*Other*
|
12
|
+
- Relaxes our dependency on the OJ gem. [#471](https://github.com/Shopify/kubernetes-deploy/pull/471)
|
13
|
+
|
3
14
|
## 0.26.3
|
4
15
|
|
5
16
|
*Bug fixes*
|
data/CONTRIBUTING.md
CHANGED
@@ -113,8 +113,9 @@ If you work for Shopify, just run `dev up`, but otherwise:
|
|
113
113
|
|
114
114
|
1. [Install kubectl version 1.10.0 or higher](https://kubernetes.io/docs/user-guide/prereqs/) and make sure it is in your path
|
115
115
|
2. [Install minikube](https://kubernetes.io/docs/getting-started-guides/minikube/#installation) (required to run the test suite)
|
116
|
-
3.
|
117
|
-
4.
|
116
|
+
3. [Install any required minikube drivers](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md) (on OS X, you may need the [hyperkit driver](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver)
|
117
|
+
4. Check out the repo
|
118
|
+
5. Run `bin/setup` to install dependencies
|
118
119
|
|
119
120
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
120
121
|
|
@@ -144,14 +145,11 @@ To see the full-color output of a specific integration test, you can use `PRINT_
|
|
144
145
|
|
145
146
|
## Releasing a new version (Shopify employees)
|
146
147
|
|
147
|
-
1.
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
If you push your commit and the tag separately, Shipit usually fails with `You need to create the v0.7.9 tag first.`. To make it find your tag, go to `Settings` > `Resynchronize this stack` > `Clear git cache`.
|
154
|
-
|
148
|
+
1. On a new branch, create a new heading in CHANGELOG.md for your version and move the entries from "Next" under it. Leave the "Next" heading in the file (this helps with the diff for rebases after the release).
|
149
|
+
1. Make sure CHANGELOG.md includes all user-facing changes since the last release. Things like test changes or refactors do not need to be included.
|
150
|
+
1. Update the version number in `version.rb`.
|
151
|
+
1. Commit your changes with message "Version x.y.z" and open a PR.
|
152
|
+
1. After merging your PR, deploy via [Shipit](https://shipit.shopify.io/shopify/kubernetes-deploy/rubygems). Shipit will automatically tag the release and upload the gem to [rubygems.org](https://rubygems.org/gems/kubernetes-deploy).
|
155
153
|
|
156
154
|
## CI (External contributors)
|
157
155
|
|
data/README.md
CHANGED
@@ -114,6 +114,8 @@ Refer to `kubernetes-deploy --help` for the authoritative set of options.
|
|
114
114
|
resource to deploy.
|
115
115
|
- `--selector`: Instructs kubernetes-deploy to only prune resources which match the specified label selector, such as `environment=staging`. If you use this option, all resource templates must specify matching labels. See [Sharing a namespace](#sharing-a-namespace) below.
|
116
116
|
|
117
|
+
> **NOTICE**: Deploy Secret resources at your own risk. Although we will fix any reported leak vectors with urgency, we cannot guarantee that sensitive information will never be logged.
|
118
|
+
|
117
119
|
### Sharing a namespace
|
118
120
|
|
119
121
|
By default, kubernetes-deploy will prune any resources in the target namespace which have the `kubectl.kubernetes.io/last-applied-configuration` annotation and are not a result of the current deployment process, on the assumption that there is a one-to-one relationship between application deployment and namespace, and that a deployment provisions all relevant resources in the namespace.
|
data/dev.yml
CHANGED
@@ -5,6 +5,10 @@ up:
|
|
5
5
|
- bundler
|
6
6
|
- homebrew:
|
7
7
|
- Caskroom/cask/minikube
|
8
|
+
- custom:
|
9
|
+
name: Install the minikube fork of driver-hyperkit
|
10
|
+
met?: command -v docker-machine-driver-hyperkit
|
11
|
+
meet: curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-hyperkit && sudo install -o root -g wheel -m 4755 docker-machine-driver-hyperkit /usr/local/bin/ && rm ./docker-machine-driver-hyperkit
|
8
12
|
- custom:
|
9
13
|
name: Minikube Cluster
|
10
14
|
met?: test $(minikube status | grep Running | wc -l) -ge 2 && $(minikube status | grep -q 'Correctly Configured')
|
data/exe/kubernetes-render
CHANGED
@@ -12,7 +12,7 @@ ARGV.options do |opts|
|
|
12
12
|
parser = KubernetesDeploy::BindingsParser.new
|
13
13
|
opts.on("--bindings=BINDINGS", "Expose additional variables to ERB templates " \
|
14
14
|
"(format: k1=v1,k2=v2, JSON string or file (JSON or YAML) path prefixed by '@')") { |b| parser.add(b) }
|
15
|
-
opts.on("--template-dir=DIR", "Set the template dir (default: config/deploy/$ENVIRONMENT)."
|
15
|
+
opts.on("--template-dir=DIR", "Set the template dir (default: config/deploy/$ENVIRONMENT).") do |d|
|
16
16
|
template_dir = d
|
17
17
|
end
|
18
18
|
opts.parse!
|
data/kubernetes-deploy.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_dependency("ejson", "~> 1.0")
|
30
30
|
spec.add_dependency("colorize", "~> 0.8")
|
31
31
|
spec.add_dependency("statsd-instrument", '~> 2.3', '>= 2.3.2')
|
32
|
-
spec.add_dependency("oj", "~> 3.
|
32
|
+
spec.add_dependency("oj", "~> 3.0")
|
33
33
|
spec.add_dependency("concurrent-ruby", "~> 1.1")
|
34
34
|
spec.add_dependency("jsonpath", "~> 0.9.6")
|
35
35
|
|
@@ -252,7 +252,7 @@ module KubernetesDeploy
|
|
252
252
|
return unless failed_resources.present?
|
253
253
|
|
254
254
|
failed_resources.each do |r|
|
255
|
-
content = File.read(r.file_path) if File.file?(r.file_path)
|
255
|
+
content = File.read(r.file_path) if File.file?(r.file_path) && !r.sensitive_template_content?
|
256
256
|
record_invalid_template(err: r.validation_error_msg, filename: File.basename(r.file_path), content: content)
|
257
257
|
end
|
258
258
|
raise FatalDeploymentError, "Template validation failed"
|
@@ -319,7 +319,13 @@ module KubernetesDeploy
|
|
319
319
|
def record_invalid_template(err:, filename:, content: nil)
|
320
320
|
debug_msg = ColorizedString.new("Invalid template: #{filename}\n").red
|
321
321
|
debug_msg += "> Error message:\n#{FormattedLogger.indent_four(err)}"
|
322
|
-
|
322
|
+
if content
|
323
|
+
debug_msg += if content =~ /kind:\s*Secret/
|
324
|
+
"\n> Template content: Suppressed because it may contain a Secret"
|
325
|
+
else
|
326
|
+
"\n> Template content:\n#{FormattedLogger.indent_four(content)}"
|
327
|
+
end
|
328
|
+
end
|
323
329
|
@logger.summary.add_paragraph(debug_msg)
|
324
330
|
end
|
325
331
|
|
@@ -445,7 +451,7 @@ module KubernetesDeploy
|
|
445
451
|
prune_whitelist.each { |type| command.push("--prune-whitelist=#{type}") }
|
446
452
|
end
|
447
453
|
|
448
|
-
output_is_sensitive = resources.any?(&:
|
454
|
+
output_is_sensitive = resources.any?(&:sensitive_template_content?)
|
449
455
|
out, err, st = kubectl.run(*command, log_failure: false, output_is_sensitive: output_is_sensitive)
|
450
456
|
|
451
457
|
if st.success?
|
@@ -473,7 +479,7 @@ module KubernetesDeploy
|
|
473
479
|
|
474
480
|
unidentified_errors = []
|
475
481
|
filenames_with_sensitive_content = resources
|
476
|
-
.select(&:
|
482
|
+
.select(&:sensitive_template_content?)
|
477
483
|
.map { |r| File.basename(r.file_path) }
|
478
484
|
|
479
485
|
err.each_line do |line|
|
@@ -62,7 +62,11 @@ module KubernetesDeploy
|
|
62
62
|
|
63
63
|
secrets.map do |secret_name, secret_spec|
|
64
64
|
validate_secret_spec(secret_name, secret_spec)
|
65
|
-
generate_secret_resource(secret_name, secret_spec["_type"], secret_spec["data"])
|
65
|
+
resource = generate_secret_resource(secret_name, secret_spec["_type"], secret_spec["data"])
|
66
|
+
unless resource.validate_definition(@kubectl)
|
67
|
+
raise EjsonSecretError, "Resulting resource Secret/#{secret_name} failed validation"
|
68
|
+
end
|
69
|
+
resource
|
66
70
|
end
|
67
71
|
end
|
68
72
|
end
|
@@ -30,15 +30,13 @@ module KubernetesDeploy
|
|
30
30
|
|
31
31
|
TIMEOUT_OVERRIDE_ANNOTATION = "kubernetes-deploy.shopify.io/timeout-override"
|
32
32
|
LAST_APPLIED_ANNOTATION = "kubectl.kubernetes.io/last-applied-configuration"
|
33
|
-
|
33
|
+
SENSITIVE_TEMPLATE_CONTENT = false
|
34
34
|
|
35
35
|
class << self
|
36
36
|
def build(namespace:, context:, definition:, logger:, statsd_tags:, crd: nil)
|
37
|
+
validate_definition_essentials(definition)
|
37
38
|
opts = { namespace: namespace, context: context, definition: definition, logger: logger,
|
38
39
|
statsd_tags: statsd_tags }
|
39
|
-
if definition["kind"].blank?
|
40
|
-
raise InvalidTemplateError.new("Template missing 'Kind'", content: definition.to_yaml)
|
41
|
-
end
|
42
40
|
if (klass = class_for_kind(definition["kind"]))
|
43
41
|
return klass.new(**opts)
|
44
42
|
end
|
@@ -53,7 +51,7 @@ module KubernetesDeploy
|
|
53
51
|
|
54
52
|
def class_for_kind(kind)
|
55
53
|
if KubernetesDeploy.const_defined?(kind)
|
56
|
-
KubernetesDeploy.const_get(kind)
|
54
|
+
KubernetesDeploy.const_get(kind)
|
57
55
|
end
|
58
56
|
rescue NameError
|
59
57
|
nil
|
@@ -66,6 +64,24 @@ module KubernetesDeploy
|
|
66
64
|
def kind
|
67
65
|
name.demodulize
|
68
66
|
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def validate_definition_essentials(definition)
|
71
|
+
debug_content = <<~STRING
|
72
|
+
apiVersion: #{definition.fetch('apiVersion', '<missing>')}
|
73
|
+
kind: #{definition.fetch('kind', '<missing>')}
|
74
|
+
metadata: #{definition.fetch('metadata', {})}
|
75
|
+
<Template body suppressed because content sensitivity could not be determined.>
|
76
|
+
STRING
|
77
|
+
if definition["kind"].blank?
|
78
|
+
raise InvalidTemplateError.new("Template is missing required field 'kind'", content: debug_content)
|
79
|
+
end
|
80
|
+
|
81
|
+
if definition.dig('metadata', 'name').blank?
|
82
|
+
raise InvalidTemplateError.new("Template is missing required field 'metadata.name'", content: debug_content)
|
83
|
+
end
|
84
|
+
end
|
69
85
|
end
|
70
86
|
|
71
87
|
def timeout
|
@@ -86,12 +102,7 @@ module KubernetesDeploy
|
|
86
102
|
|
87
103
|
def initialize(namespace:, context:, definition:, logger:, statsd_tags: [])
|
88
104
|
# subclasses must also set these if they define their own initializer
|
89
|
-
@name = definition.dig("metadata", "name")
|
90
|
-
unless @name.present?
|
91
|
-
logger.summary.add_paragraph("Rendered template content:\n#{definition.to_yaml}")
|
92
|
-
raise FatalDeploymentError, "Template is missing required field metadata.name"
|
93
|
-
end
|
94
|
-
|
105
|
+
@name = definition.dig("metadata", "name").to_s
|
95
106
|
@optional_statsd_tags = statsd_tags
|
96
107
|
@namespace = namespace
|
97
108
|
@context = context
|
@@ -113,9 +124,9 @@ module KubernetesDeploy
|
|
113
124
|
validate_timeout_annotation
|
114
125
|
|
115
126
|
command = ["create", "-f", file_path, "--dry-run", "--output=name"]
|
116
|
-
_, err, st = kubectl.run(*command, log_failure: false, output_is_sensitive:
|
127
|
+
_, err, st = kubectl.run(*command, log_failure: false, output_is_sensitive: sensitive_template_content?)
|
117
128
|
return true if st.success?
|
118
|
-
if
|
129
|
+
if sensitive_template_content?
|
119
130
|
@validation_errors << <<-EOS
|
120
131
|
Validation for #{id} failed. Detailed information is unavailable as the raw error may contain sensitive data.
|
121
132
|
EOS
|
@@ -322,8 +333,8 @@ module KubernetesDeploy
|
|
322
333
|
end
|
323
334
|
end
|
324
335
|
|
325
|
-
def
|
326
|
-
self.class::
|
336
|
+
def sensitive_template_content?
|
337
|
+
self.class::SENSITIVE_TEMPLATE_CONTENT
|
327
338
|
end
|
328
339
|
|
329
340
|
class Event
|
@@ -24,7 +24,7 @@ module KubernetesDeploy
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def proxy_deployment_ready?
|
27
|
-
return false unless status = @proxy_deployment["status"]
|
27
|
+
return false unless (status = @proxy_deployment["status"])
|
28
28
|
# all cloudsql-proxy pods are running
|
29
29
|
status.fetch("availableReplicas", -1) == status.fetch("replicas", 0)
|
30
30
|
end
|
@@ -146,7 +146,7 @@ module KubernetesDeploy
|
|
146
146
|
end
|
147
147
|
|
148
148
|
def ready?
|
149
|
-
return false unless status_data = @instance_data["status"]
|
149
|
+
return false unless (status_data = @instance_data["status"])
|
150
150
|
ready_condition = status_data.fetch("conditions", []).find { |condition| condition["type"] == "Ready" }
|
151
151
|
ready_condition.present? && (ready_condition["status"] == "True")
|
152
152
|
end
|
@@ -210,8 +210,7 @@ module KubernetesDeploy
|
|
210
210
|
elsif limbo_reason == "CrashLoopBackOff"
|
211
211
|
exit_code = @status.dig('lastState', 'terminated', 'exitCode')
|
212
212
|
"Crashing repeatedly (exit #{exit_code}). See logs for more information."
|
213
|
-
elsif
|
214
|
-
limbo_message.match(/(?:not found)|(?:back-off)/i)
|
213
|
+
elsif limbo_reason == "ErrImagePull" && limbo_message.match(/not found/i)
|
215
214
|
"Failed to pull image #{@image}. "\
|
216
215
|
"Did you wait for it to be built and pushed to the registry before deploying?"
|
217
216
|
elsif limbo_reason == "CreateContainerConfigError"
|
@@ -29,7 +29,7 @@ module KubernetesDeploy
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def deployment_ready?
|
32
|
-
return false unless status = @deployment["status"]
|
32
|
+
return false unless (status = @deployment["status"])
|
33
33
|
# all redis pods are running
|
34
34
|
status.fetch("availableReplicas", -1) == status.fetch("replicas", 0)
|
35
35
|
end
|
@@ -51,7 +51,7 @@ module KubernetesDeploy
|
|
51
51
|
|
52
52
|
def fetch_by_kind(kind)
|
53
53
|
resource_class = KubernetesResource.class_for_kind(kind)
|
54
|
-
output_is_sensitive = resource_class.nil? ? false : resource_class::
|
54
|
+
output_is_sensitive = resource_class.nil? ? false : resource_class::SENSITIVE_TEMPLATE_CONTENT
|
55
55
|
raw_json, _, st = @kubectl.run("get", kind, "--chunk-size=0", attempts: 5, output: "json",
|
56
56
|
output_is_sensitive: output_is_sensitive)
|
57
57
|
raise KubectlError unless st.success?
|
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.26.
|
4
|
+
version: 0.26.4
|
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: 2019-04-
|
12
|
+
date: 2019-04-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -107,14 +107,14 @@ dependencies:
|
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '3.
|
110
|
+
version: '3.0'
|
111
111
|
type: :runtime
|
112
112
|
prerelease: false
|
113
113
|
version_requirements: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '3.
|
117
|
+
version: '3.0'
|
118
118
|
- !ruby/object:Gem::Dependency
|
119
119
|
name: concurrent-ruby
|
120
120
|
requirement: !ruby/object:Gem::Requirement
|