kubernetes-deploy 0.14.0 → 0.14.1
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 +10 -0
- data/README.md +1 -1
- data/exe/kubernetes-deploy +3 -7
- data/lib/kubernetes-deploy.rb +1 -0
- data/lib/kubernetes-deploy/bindings_parser.rb +54 -0
- data/lib/kubernetes-deploy/deploy_task.rb +9 -2
- data/lib/kubernetes-deploy/kubeclient_builder.rb +13 -5
- data/lib/kubernetes-deploy/kubernetes_resource/pod.rb +4 -2
- data/lib/kubernetes-deploy/kubernetes_resource/service.rb +21 -2
- data/lib/kubernetes-deploy/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b7eaf966de6685ee13686190feda92f7d5e249c
|
4
|
+
data.tar.gz: 7bc442ae69145779cd8965caababf22545a5d954
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 983f99b3be92381d2838bc7b7cd4d9efd4220e9b13cd68d795d1d5523cd550d15effea7da8dc273d6dec8825e23372a63ff82a05e577ebcbdac0a3c2b9c2095b
|
7
|
+
data.tar.gz: 28eb00deaa911348e3d27be549bcd0c788e8efc00977edd1c3986521b9e82367b06a8d80a258a371ec9dcd9d4b9dc7100d6e4856f0f98596fd2ab2b43dfd005b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
### 0.14.1
|
2
|
+
*Bug Fixes*
|
3
|
+
- Make deployments whose pods crash because of CreateContainerConfigError fail fast in 1.8+ too (they would previously time out).
|
4
|
+
- Fix crashes when deploying ExternalName services or services without selectors ([#211](https://github.com/Shopify/kubernetes-deploy/pull/211))
|
5
|
+
- Predeploy ServiceAccount resources ([#221](https://github.com/Shopify/kubernetes-deploy/pull/221))
|
6
|
+
|
7
|
+
*Enhancements*
|
8
|
+
- Make it possible to pass bindings (via the --bindings flag) for which the value contains commas or is a JSON encoded hash ([#219](https://github.com/Shopify/kubernetes-deploy/pull/219))
|
9
|
+
- Support KUBECONFIG referencing multiple files ([#222](https://github.com/Shopify/kubernetes-deploy/pull/222))
|
10
|
+
|
1
11
|
### 0.14.0
|
2
12
|
*Bug Fixes*
|
3
13
|
- Fix incorrect timeouts occasionally observed on deployments using progressDeadlineSeconds in Kubernetes <1.7.7
|
data/README.md
CHANGED
@@ -91,7 +91,7 @@ This repo also includes related tools for [running tasks](#kubernetes-run) and [
|
|
91
91
|
*Environment variables:*
|
92
92
|
|
93
93
|
- `$REVISION` **(required)**: the SHA of the commit you are deploying. Will be exposed to your ERB templates as `current_sha`.
|
94
|
-
- `$KUBECONFIG` **(required)**: points to
|
94
|
+
- `$KUBECONFIG` **(required)**: points to one or multiple valid kubeconfig files that include the context you want to deploy to. File names are separated by colon for Linux and Mac, and semi-colon for Windows.
|
95
95
|
- `$ENVIRONMENT`: used to set the deploy directory to `config/deploy/$ENVIRONMENT`. You can use the `--template-dir=DIR` option instead if you prefer (**one or the other is required**).
|
96
96
|
- `$GOOGLE_APPLICATION_CREDENTIALS`: points to the credentials for an authenticated service account (required if your kubeconfig `user`'s auth provider is GCP)
|
97
97
|
|
data/exe/kubernetes-deploy
CHANGED
@@ -12,13 +12,9 @@ bindings = {}
|
|
12
12
|
verbose_log_prefix = false
|
13
13
|
|
14
14
|
ARGV.options do |opts|
|
15
|
-
opts.on("--bindings=BINDINGS",
|
16
|
-
|
17
|
-
|
18
|
-
raise "key for value #{v} is blank!" if k.blank?
|
19
|
-
raise "value for key #{k} is blank!" if v.blank?
|
20
|
-
acc[k] = v
|
21
|
-
end
|
15
|
+
opts.on("--bindings=BINDINGS", "Expose additional variables to ERB templates " \
|
16
|
+
"(format: k1=v1,k2=v2 or JSON)") do |binds|
|
17
|
+
bindings = KubernetesDeploy::BindingsParser.parse(binds)
|
22
18
|
end
|
23
19
|
|
24
20
|
opts.on("--skip-wait", "Skip verification of non-priority-resource success (not recommended)") { skip_wait = true }
|
data/lib/kubernetes-deploy.rb
CHANGED
@@ -16,6 +16,7 @@ require 'kubernetes-deploy/formatted_logger'
|
|
16
16
|
require 'kubernetes-deploy/deploy_task'
|
17
17
|
require 'kubernetes-deploy/statsd'
|
18
18
|
require 'kubernetes-deploy/concurrency'
|
19
|
+
require 'kubernetes-deploy/bindings_parser'
|
19
20
|
|
20
21
|
module KubernetesDeploy
|
21
22
|
KubernetesDeploy::StatsD.build
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'json'
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
module KubernetesDeploy
|
6
|
+
module BindingsParser
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def parse(string)
|
10
|
+
bindings = parse_json(string) || parse_csv(string)
|
11
|
+
|
12
|
+
unless bindings
|
13
|
+
raise ArgumentError, "Failed to parse bindings."
|
14
|
+
end
|
15
|
+
|
16
|
+
bindings
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def parse_json(string)
|
22
|
+
bindings = JSON.parse(string)
|
23
|
+
|
24
|
+
unless bindings.is_a?(Hash)
|
25
|
+
raise ArgumentError, "Expected JSON data to be a hash."
|
26
|
+
end
|
27
|
+
|
28
|
+
bindings
|
29
|
+
rescue JSON::ParserError
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_csv(string)
|
34
|
+
lines = CSV.parse(string)
|
35
|
+
bindings = {}
|
36
|
+
|
37
|
+
lines.each do |line|
|
38
|
+
line.each do |binding|
|
39
|
+
key, value = binding.split('=', 2)
|
40
|
+
|
41
|
+
if key.blank?
|
42
|
+
raise ArgumentError, "key is blank"
|
43
|
+
end
|
44
|
+
|
45
|
+
bindings[key] = value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
bindings
|
50
|
+
rescue CSV::MalformedCSVError
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -48,6 +48,7 @@ module KubernetesDeploy
|
|
48
48
|
Bugsnag
|
49
49
|
ConfigMap
|
50
50
|
PersistentVolumeClaim
|
51
|
+
ServiceAccount
|
51
52
|
Pod
|
52
53
|
)
|
53
54
|
PROTECTED_NAMESPACES = %w(
|
@@ -277,8 +278,14 @@ module KubernetesDeploy
|
|
277
278
|
errors = []
|
278
279
|
if ENV["KUBECONFIG"].blank?
|
279
280
|
errors << "$KUBECONFIG not set"
|
280
|
-
elsif
|
281
|
-
errors << "Kube config not
|
281
|
+
elsif config_files.empty?
|
282
|
+
errors << "Kube config file name(s) not set in $KUBECONFIG"
|
283
|
+
else
|
284
|
+
config_files.each do |f|
|
285
|
+
unless File.file?(f)
|
286
|
+
errors << "Kube config not found at #{f}"
|
287
|
+
end
|
288
|
+
end
|
282
289
|
end
|
283
290
|
|
284
291
|
if @current_sha.blank?
|
@@ -6,7 +6,8 @@ module KubernetesDeploy
|
|
6
6
|
module KubeclientBuilder
|
7
7
|
class ContextMissingError < FatalDeploymentError
|
8
8
|
def initialize(context_name)
|
9
|
-
super("`#{context_name}` context must be configured in your
|
9
|
+
super("`#{context_name}` context must be configured in your " \
|
10
|
+
"KUBECONFIG file(s) (#{ENV['KUBECONFIG']}).")
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -44,10 +45,12 @@ module KubernetesDeploy
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def _build_kubeclient(api_version:, context:, endpoint_path: nil)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
# Find a context defined in kube conf files that matches the input context by name
|
49
|
+
friendly_configs = config_files.map { |f| GoogleFriendlyConfig.read(f) }
|
50
|
+
config = friendly_configs.find { |c| c.contexts.include?(context) }
|
51
|
+
|
52
|
+
raise ContextMissingError, context unless config
|
53
|
+
|
51
54
|
kube_context = config.context(context)
|
52
55
|
|
53
56
|
client = Kubeclient::Client.new(
|
@@ -59,5 +62,10 @@ module KubernetesDeploy
|
|
59
62
|
client.discover
|
60
63
|
client
|
61
64
|
end
|
65
|
+
|
66
|
+
def config_files
|
67
|
+
# Split the list by colon for Linux and Mac, and semicolon for Windows.
|
68
|
+
ENV.fetch("KUBECONFIG").split(/[:;]/).map!(&:strip).reject(&:empty?)
|
69
|
+
end
|
62
70
|
end
|
63
71
|
end
|
@@ -202,9 +202,11 @@ module KubernetesDeploy
|
|
202
202
|
"Failed to pull image #{@image}. "\
|
203
203
|
"Did you wait for it to be built and pushed to the registry before deploying?"
|
204
204
|
elsif limbo_message == "Generate Container Config Failed"
|
205
|
-
# reason/message are backwards
|
206
|
-
#
|
205
|
+
# reason/message are backwards in <1.8.0 (next condition used by 1.8.0+)
|
206
|
+
# Fixed by https://github.com/kubernetes/kubernetes/commit/df41787b1a3f51b73fb6db8a2203f0a7c7c92931
|
207
207
|
"Failed to generate container configuration: #{limbo_reason}"
|
208
|
+
elsif limbo_reason == "CreateContainerConfigError"
|
209
|
+
"Failed to generate container configuration: #{limbo_message}"
|
208
210
|
end
|
209
211
|
end
|
210
212
|
|
@@ -11,7 +11,9 @@ module KubernetesDeploy
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def status
|
14
|
-
if
|
14
|
+
if !requires_endpoints?
|
15
|
+
"Doesn't require any endpoint"
|
16
|
+
elsif @num_pods_selected.blank?
|
15
17
|
"Failed to count related pods"
|
16
18
|
elsif selects_some_pods?
|
17
19
|
"Selects at least 1 pod"
|
@@ -21,6 +23,7 @@ module KubernetesDeploy
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def deploy_succeeded?
|
26
|
+
return exists? unless requires_endpoints?
|
24
27
|
# We can't use endpoints if we want the service to be able to fail fast when the pods are down
|
25
28
|
exposes_zero_replica_deployment? || selects_some_pods?
|
26
29
|
end
|
@@ -44,22 +47,34 @@ module KubernetesDeploy
|
|
44
47
|
@related_deployment_replicas == 0
|
45
48
|
end
|
46
49
|
|
50
|
+
def requires_endpoints?
|
51
|
+
# service of type External don't have endpoints
|
52
|
+
return false if external_name_svc?
|
53
|
+
|
54
|
+
# problem counting replicas - by default, assume endpoints are required
|
55
|
+
return true if @related_deployment_replicas.blank?
|
56
|
+
|
57
|
+
@related_deployment_replicas > 0
|
58
|
+
end
|
59
|
+
|
47
60
|
def selects_some_pods?
|
48
61
|
return false unless @num_pods_selected
|
49
62
|
@num_pods_selected > 0
|
50
63
|
end
|
51
64
|
|
52
65
|
def selector
|
53
|
-
@selector ||= @definition["spec"]
|
66
|
+
@selector ||= @definition["spec"].fetch("selector", []).map { |k, v| "#{k}=#{v}" }.join(",")
|
54
67
|
end
|
55
68
|
|
56
69
|
def fetch_related_pod_count
|
70
|
+
return 0 unless selector.present?
|
57
71
|
raw_json, _err, st = kubectl.run("get", "pods", "--selector=#{selector}", "--output=json")
|
58
72
|
return unless st.success?
|
59
73
|
JSON.parse(raw_json)["items"].length
|
60
74
|
end
|
61
75
|
|
62
76
|
def fetch_related_replica_count
|
77
|
+
return 0 unless selector.present?
|
63
78
|
raw_json, _err, st = kubectl.run("get", "deployments", "--selector=#{selector}", "--output=json")
|
64
79
|
return unless st.success?
|
65
80
|
|
@@ -67,5 +82,9 @@ module KubernetesDeploy
|
|
67
82
|
return unless deployments.length == 1
|
68
83
|
deployments.first["spec"]["replicas"].to_i
|
69
84
|
end
|
85
|
+
|
86
|
+
def external_name_svc?
|
87
|
+
@definition["spec"]["type"] == "ExternalName"
|
88
|
+
end
|
70
89
|
end
|
71
90
|
end
|
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.14.
|
4
|
+
version: 0.14.1
|
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: 2017-
|
12
|
+
date: 2017-12-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -223,6 +223,7 @@ files:
|
|
223
223
|
- exe/kubernetes-run
|
224
224
|
- kubernetes-deploy.gemspec
|
225
225
|
- lib/kubernetes-deploy.rb
|
226
|
+
- lib/kubernetes-deploy/bindings_parser.rb
|
226
227
|
- lib/kubernetes-deploy/concurrency.rb
|
227
228
|
- lib/kubernetes-deploy/deferred_summary_logging.rb
|
228
229
|
- lib/kubernetes-deploy/deploy_task.rb
|