kubernetes-deploy 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|