kubernetes-deploy 0.24.0 → 0.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/README.md +1 -1
- data/kubernetes-deploy.gemspec +1 -1
- data/lib/kubernetes-deploy/deploy_task.rb +2 -2
- data/lib/kubernetes-deploy/ejson_secret_provisioner.rb +3 -3
- data/lib/kubernetes-deploy/kubeclient_builder/kube_config.rb +21 -0
- data/lib/kubernetes-deploy/kubeclient_builder.rb +3 -4
- data/lib/kubernetes-deploy/kubernetes_resource/config_map.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/deployment.rb +12 -2
- data/lib/kubernetes-deploy/kubernetes_resource/ingress.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/persistent_volume_claim.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/pod_disruption_budget.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/pod_template.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/resource_quota.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/role.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/role_binding.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource/service_account.rb +1 -1
- data/lib/kubernetes-deploy/kubernetes_resource.rb +1 -1
- data/lib/kubernetes-deploy/restart_task.rb +5 -13
- data/lib/kubernetes-deploy/runner_task.rb +14 -13
- data/lib/kubernetes-deploy/version.rb +1 -1
- metadata +5 -5
- data/lib/kubernetes-deploy/kubeclient_builder/google_friendly_config.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f35ca56d7b0ec844c55ff82157238409f2c21db3a9d83f870a73cc3305ee0b8
|
4
|
+
data.tar.gz: a9d9e566c21f699e9f066cd5bd505cd9c9ef9466a0180bb7563e9004211a8184
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c3e2b2a8267d997e7d8859d6238d70f8a052bb423c8526f6e0f0490efe9de97da54ec1de0737f229f2682b04ba0b385ed2cc54caea3cc8276536026abb660cd
|
7
|
+
data.tar.gz: 98a21af1679cec75a00a6f81981b5a092888113c81f74d03eb967ba07da8b722db06c1394202a2de0fb943df5d784b3e95de15f653682e9c4555a4b595018a45
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,16 @@
|
|
1
|
-
##
|
1
|
+
## 0.25.0
|
2
|
+
|
3
|
+
*Features*
|
4
|
+
- Support timeout overrides on deployments ([#414](https://github.com/Shopify/kubernetes-deploy/pull/414))
|
5
|
+
|
6
|
+
*Bug fixes*
|
7
|
+
- Attempting to deploy from a directory that only contains `secrets.ejson` will no longer fail deploy ([#416](https://github.com/Shopify/kubernetes-deploy/pull/416))
|
8
|
+
- Remove the risk of sending decrypted EJSON secrets to output([#431](https://github.com/Shopify/kubernetes-deploy/pull/431))
|
9
|
+
|
10
|
+
*Other*
|
11
|
+
- Update kubeclient gem to 4.2.2. Note this replaces the `KubeclientBuilder::GoogleFriendlyConfig` class with `KubeclientBuilder::KubeConfig` ([#418](https://github.com/Shopify/kubernetes-deploy/pull/418)). This resolves [#396](https://github.com/Shopify/kubernetes-deploy/issues/396) and should allow us to support more authentication methods (e.g. `exec` for EKS).
|
12
|
+
- Invalid context when using `kubernetes-run` gives more descriptive error([#423](https://github.com/Shopify/kubernetes-deploy/pull/423))
|
13
|
+
- When resources are not found, instead of being `Unknown`, they are now labelled as `Not Found`([#427](https://github.com/Shopify/kubernetes-deploy/pull/427))
|
2
14
|
|
3
15
|
## 0.24.0
|
4
16
|
|
data/README.md
CHANGED
@@ -227,7 +227,7 @@ This is a limitation of the current implementation.
|
|
227
227
|
### Customizing behaviour with annotations
|
228
228
|
- `kubernetes-deploy.shopify.io/timeout-override`: Override the tool's hard timeout for one specific resource. Both full ISO8601 durations and the time portion of ISO8601 durations are valid. Value must be between 1 second and 24 hours.
|
229
229
|
- _Example values_: 45s / 3m / 1h / PT0.25H
|
230
|
-
- _Compatibility_: all resource types
|
230
|
+
- _Compatibility_: all resource types
|
231
231
|
- `kubernetes-deploy.shopify.io/required-rollout`: Modifies how much of the rollout needs to finish
|
232
232
|
before the deployment is considered successful.
|
233
233
|
- _Compatibility_: Deployment
|
data/kubernetes-deploy.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
|
25
25
|
spec.required_ruby_version = '>= 2.3.0'
|
26
26
|
spec.add_dependency("activesupport", ">= 5.0")
|
27
|
-
spec.add_dependency("kubeclient", "~>
|
27
|
+
spec.add_dependency("kubeclient", "~> 4.0")
|
28
28
|
spec.add_dependency("googleauth", "~> 0.6.6") # https://github.com/google/google-auth-library-ruby/issues/153
|
29
29
|
spec.add_dependency("ejson", "~> 1.0")
|
30
30
|
spec.add_dependency("colorize", "~> 0.8")
|
@@ -324,8 +324,8 @@ module KubernetesDeploy
|
|
324
324
|
|
325
325
|
if !File.directory?(@template_dir)
|
326
326
|
errors << "Template directory `#{@template_dir}` doesn't exist"
|
327
|
-
elsif Dir.entries(@template_dir).none? { |file| file =~
|
328
|
-
errors << "`#{@template_dir}` doesn't contain valid templates (postfix .yml
|
327
|
+
elsif Dir.entries(@template_dir).none? { |file| file =~ /(\.ya?ml(\.erb)?)$|(secrets\.ejson)$/ }
|
328
|
+
errors << "`#{@template_dir}` doesn't contain valid templates (secrets.ejson or postfix .yml, .yml.erb)"
|
329
329
|
end
|
330
330
|
|
331
331
|
if @namespace.blank?
|
@@ -74,7 +74,7 @@ module KubernetesDeploy
|
|
74
74
|
prune_count += 1
|
75
75
|
out, err, st = @kubectl.run("delete", "secret", secret_name)
|
76
76
|
@logger.debug(out)
|
77
|
-
raise EjsonSecretError,
|
77
|
+
raise EjsonSecretError, "Failed to prune secrets" unless st.success?
|
78
78
|
end
|
79
79
|
@logger.summary.add_action("pruned #{prune_count} #{'secret'.pluralize(prune_count)}") if prune_count > 0
|
80
80
|
end
|
@@ -121,7 +121,7 @@ module KubernetesDeploy
|
|
121
121
|
|
122
122
|
out, err, st = @kubectl.run("apply", "--filename=#{file.path}")
|
123
123
|
@logger.debug(out)
|
124
|
-
raise EjsonSecretError,
|
124
|
+
raise EjsonSecretError, "Failed to create or update secrets" unless st.success?
|
125
125
|
ensure
|
126
126
|
file&.unlink
|
127
127
|
end
|
@@ -181,7 +181,7 @@ module KubernetesDeploy
|
|
181
181
|
raise EjsonSecretError, out_err unless st.success?
|
182
182
|
JSON.parse(out_err)
|
183
183
|
rescue JSON::ParserError => e
|
184
|
-
raise EjsonSecretError, "Failed to parse decrypted ejson
|
184
|
+
raise EjsonSecretError, "Failed to parse decrypted ejson"
|
185
185
|
end
|
186
186
|
|
187
187
|
def fetch_private_key_from_secret
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'googleauth'
|
4
|
+
module KubernetesDeploy
|
5
|
+
module KubeclientBuilder
|
6
|
+
class KubeConfig < Kubeclient::Config
|
7
|
+
def self.read(filename)
|
8
|
+
parsed = YAML.safe_load(File.read(filename), [Date, Time])
|
9
|
+
new(parsed, File.dirname(filename))
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetch_user_auth_options(user)
|
13
|
+
if user.dig('auth-provider', 'name') == 'gcp'
|
14
|
+
{ bearer_token: Kubeclient::GoogleApplicationDefaultCredentials.token }
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'kubeclient'
|
3
|
-
require 'kubernetes-deploy/kubeclient_builder/
|
3
|
+
require 'kubernetes-deploy/kubeclient_builder/kube_config'
|
4
4
|
|
5
5
|
module KubernetesDeploy
|
6
6
|
module KubeclientBuilder
|
@@ -86,13 +86,12 @@ module KubernetesDeploy
|
|
86
86
|
|
87
87
|
def _build_kubeclient(api_version:, context:, endpoint_path: nil)
|
88
88
|
# Find a context defined in kube conf files that matches the input context by name
|
89
|
-
|
90
|
-
config =
|
89
|
+
configs = config_files.map { |f| KubeConfig.read(f) }
|
90
|
+
config = configs.find { |c| c.contexts.include?(context) }
|
91
91
|
|
92
92
|
raise ContextMissingError, context unless config
|
93
93
|
|
94
94
|
kube_context = config.context(context)
|
95
|
-
|
96
95
|
client = Kubeclient::Client.new(
|
97
96
|
"#{kube_context.api_endpoint}#{endpoint_path}",
|
98
97
|
api_version,
|
@@ -63,7 +63,9 @@ module KubernetesDeploy
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def timeout_message
|
66
|
-
reason_msg = if
|
66
|
+
reason_msg = if timeout_override
|
67
|
+
STANDARD_TIMEOUT_MESSAGE
|
68
|
+
elsif progress_condition.present?
|
67
69
|
"Timeout reason: #{progress_condition['reason']}"
|
68
70
|
else
|
69
71
|
"Timeout reason: hard deadline for #{type}"
|
@@ -73,11 +75,19 @@ module KubernetesDeploy
|
|
73
75
|
end
|
74
76
|
|
75
77
|
def pretty_timeout_type
|
76
|
-
|
78
|
+
if timeout_override
|
79
|
+
"timeout override: #{timeout_override}s"
|
80
|
+
elsif progress_deadline.present?
|
81
|
+
"progress deadline: #{progress_deadline}s"
|
82
|
+
else
|
83
|
+
super
|
84
|
+
end
|
77
85
|
end
|
78
86
|
|
79
87
|
def deploy_timed_out?
|
80
88
|
return false if deploy_failed?
|
89
|
+
return super if timeout_override
|
90
|
+
|
81
91
|
# Do not use the hard timeout if progress deadline is set
|
82
92
|
progress_condition.present? ? deploy_failing_to_progress? : super
|
83
93
|
end
|
@@ -112,12 +112,8 @@ module KubernetesDeploy
|
|
112
112
|
def verify_namespace
|
113
113
|
kubeclient.get_namespace(@namespace)
|
114
114
|
@logger.info("Namespace #{@namespace} found in context #{@context}")
|
115
|
-
rescue
|
116
|
-
|
117
|
-
raise NamespaceNotFoundError.new(@namespace, @context)
|
118
|
-
else
|
119
|
-
raise
|
120
|
-
end
|
115
|
+
rescue Kubeclient::ResourceNotFoundError
|
116
|
+
raise NamespaceNotFoundError.new(@namespace, @context)
|
121
117
|
end
|
122
118
|
|
123
119
|
def patch_deployment_with_restart(record)
|
@@ -133,7 +129,7 @@ module KubernetesDeploy
|
|
133
129
|
begin
|
134
130
|
patch_deployment_with_restart(record)
|
135
131
|
@logger.info("Triggered `#{record.metadata.name}` restart")
|
136
|
-
rescue Kubeclient::
|
132
|
+
rescue Kubeclient::HttpError => e
|
137
133
|
raise RestartAPIError.new(record.metadata.name, e.message)
|
138
134
|
end
|
139
135
|
end
|
@@ -144,12 +140,8 @@ module KubernetesDeploy
|
|
144
140
|
record = nil
|
145
141
|
begin
|
146
142
|
record = v1beta1_kubeclient.get_deployment(name, @namespace)
|
147
|
-
rescue
|
148
|
-
|
149
|
-
raise FatalRestartError, "Deployment `#{name}` not found in namespace `#{@namespace}`"
|
150
|
-
else
|
151
|
-
raise
|
152
|
-
end
|
143
|
+
rescue Kubeclient::ResourceNotFoundError
|
144
|
+
raise FatalRestartError, "Deployment `#{name}` not found in namespace `#{@namespace}`"
|
153
145
|
end
|
154
146
|
record
|
155
147
|
end
|
@@ -64,7 +64,7 @@ module KubernetesDeploy
|
|
64
64
|
kubeclient.create_pod(pod.to_kubeclient_resource)
|
65
65
|
@pod_name = pod.name
|
66
66
|
@logger.info("Pod creation succeeded")
|
67
|
-
rescue
|
67
|
+
rescue Kubeclient::HttpError => e
|
68
68
|
msg = "Failed to create pod: #{e.class.name}: #{e.message}"
|
69
69
|
@logger.summary.add_paragraph(msg)
|
70
70
|
raise FatalDeploymentError, msg
|
@@ -122,9 +122,13 @@ module KubernetesDeploy
|
|
122
122
|
begin
|
123
123
|
kubeclient.get_namespace(@namespace) if @namespace.present?
|
124
124
|
@logger.info("Using namespace '#{@namespace}' in context '#{@context}'")
|
125
|
-
|
126
|
-
|
127
|
-
errors <<
|
125
|
+
|
126
|
+
rescue Kubeclient::ResourceNotFoundError
|
127
|
+
errors << "Namespace was not found"
|
128
|
+
rescue Kubeclient::HttpError
|
129
|
+
errors << "Could not connect to kubernetes cluster"
|
130
|
+
rescue KubernetesDeploy::KubeclientBuilder::ContextMissingError
|
131
|
+
errors << "Could not connect to kubernetes cluster - context invalid"
|
128
132
|
end
|
129
133
|
|
130
134
|
unless errors.empty?
|
@@ -140,16 +144,13 @@ module KubernetesDeploy
|
|
140
144
|
|
141
145
|
def get_template(template_name)
|
142
146
|
pod_template = kubeclient.get_pod_template(template_name, @namespace)
|
143
|
-
|
144
147
|
pod_template.template
|
145
|
-
rescue
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
raise FatalKubeAPIError, "Error retrieving pod template: #{error.class.name}: #{error.message}"
|
152
|
-
end
|
148
|
+
rescue Kubeclient::ResourceNotFoundError
|
149
|
+
msg = "Pod template `#{template_name}` not found in namespace `#{@namespace}`, context `#{@context}`"
|
150
|
+
@logger.summary.add_paragraph(msg)
|
151
|
+
raise TaskTemplateMissingError, msg
|
152
|
+
rescue Kubeclient::HttpError => error
|
153
|
+
raise FatalKubeAPIError, "Error retrieving pod template: #{error.class.name}: #{error.message}"
|
153
154
|
end
|
154
155
|
|
155
156
|
def build_pod_definition(base_template)
|
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.25.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: 2019-
|
12
|
+
date: 2019-02-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '4.0'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '4.0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: googleauth
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -272,7 +272,7 @@ files:
|
|
272
272
|
- lib/kubernetes-deploy/errors.rb
|
273
273
|
- lib/kubernetes-deploy/formatted_logger.rb
|
274
274
|
- lib/kubernetes-deploy/kubeclient_builder.rb
|
275
|
-
- lib/kubernetes-deploy/kubeclient_builder/
|
275
|
+
- lib/kubernetes-deploy/kubeclient_builder/kube_config.rb
|
276
276
|
- lib/kubernetes-deploy/kubectl.rb
|
277
277
|
- lib/kubernetes-deploy/kubernetes_resource.rb
|
278
278
|
- lib/kubernetes-deploy/kubernetes_resource/cloudsql.rb
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'googleauth'
|
4
|
-
module KubernetesDeploy
|
5
|
-
module KubeclientBuilder
|
6
|
-
class GoogleFriendlyConfig < Kubeclient::Config
|
7
|
-
def fetch_user_auth_options(user)
|
8
|
-
if user.dig('auth-provider', 'name') == 'gcp'
|
9
|
-
{ bearer_token: new_token }
|
10
|
-
else
|
11
|
-
super
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.read(filename)
|
16
|
-
new(YAML.safe_load(File.read(filename), [Time]), File.dirname(filename))
|
17
|
-
end
|
18
|
-
|
19
|
-
def new_token
|
20
|
-
scopes = ['https://www.googleapis.com/auth/cloud-platform']
|
21
|
-
authorization = Google::Auth.get_application_default(scopes)
|
22
|
-
|
23
|
-
authorization.apply({})
|
24
|
-
|
25
|
-
authorization.access_token
|
26
|
-
|
27
|
-
rescue Signet::AuthorizationError => e
|
28
|
-
err_message = json_error_message(e.response.body) || e.message
|
29
|
-
raise KubeException.new(e.response.status, err_message, e.response.body)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def json_error_message(body)
|
35
|
-
err = JSON.parse(body || '') || {}
|
36
|
-
err['message']
|
37
|
-
rescue JSON::ParserError
|
38
|
-
nil
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|