kubernetes-deploy 0.7.4 → 0.7.5
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8974c6df435df28dab80164ebdea271275813e2b
|
4
|
+
data.tar.gz: a4d53b653bb5cfa44307f92f865bcdf08a5c1540
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f2d103ec8b209060c2bcfcb426ac7a7ed002770ac45f2e5ca1aed2d918e86dc6636509ce0eb26610702cf29689b57e48696e41d99a64c2d7ead4a4ac0169ac6
|
7
|
+
data.tar.gz: 2d7f6b144b8c8af3d577ec8fd4f1636b6e274510df9b32036b7f1e4865abc71b3a75eea03c7427a7c46cce9b63019b85bf3a2ce242b0673ea72e9cc6d7ae0b3e
|
@@ -154,25 +154,18 @@ module KubernetesDeploy
|
|
154
154
|
# Returns a hash in the following format:
|
155
155
|
# {
|
156
156
|
# "pod/web-1" => [
|
157
|
-
#
|
158
|
-
#
|
157
|
+
# "Pulling: pulling image "hello-world:latest" (1 events)",
|
158
|
+
# "Pulled: Successfully pulled image "hello-world:latest" (1 events)"
|
159
159
|
# ]
|
160
160
|
# }
|
161
161
|
def fetch_events
|
162
162
|
return {} unless exists?
|
163
|
-
|
164
|
-
out, _err, st = kubectl.run("get", "events",
|
165
|
-
%(--output=jsonpath={range .items[?(@.involvedObject.name=="#{name}")]}#{fields}\n{end}))
|
163
|
+
out, _err, st = kubectl.run("get", "events", "--output=go-template=#{Event.go_template_for(type, name)}")
|
166
164
|
return {} unless st.success?
|
167
165
|
|
168
166
|
event_collector = Hash.new { |hash, key| hash[key] = [] }
|
169
|
-
|
170
|
-
|
171
|
-
subject_kind = pieces[0]
|
172
|
-
# jsonpath can only filter by one thing at a time, and we chose involvedObject.name
|
173
|
-
# This means we still need to filter by involvedObject.kind here to make sure we only retain relevant events
|
174
|
-
next unless subject_kind.downcase == type.downcase
|
175
|
-
events[id] << "#{pieces[3] || 'Unknown'}: #{pieces[2]} (#{pieces[1]} events)" # Reason: Message (X events)
|
167
|
+
Event.extract_all_from_go_template_blob(out).each_with_object(event_collector) do |candidate, events|
|
168
|
+
events[id] << candidate.to_s if candidate.seen_since?(@deploy_started - 5.seconds)
|
176
169
|
end
|
177
170
|
end
|
178
171
|
|
@@ -192,5 +185,61 @@ module KubernetesDeploy
|
|
192
185
|
def kubectl
|
193
186
|
@kubectl ||= Kubectl.new(namespace: @namespace, context: @context, logger: @logger, log_failure_by_default: false)
|
194
187
|
end
|
188
|
+
|
189
|
+
class Event
|
190
|
+
EVENT_SEPARATOR = "ENDEVENT--BEGINEVENT"
|
191
|
+
FIELD_SEPARATOR = "ENDFIELD--BEGINFIELD"
|
192
|
+
FIELDS = %w(
|
193
|
+
.involvedObject.kind
|
194
|
+
.involvedObject.name
|
195
|
+
.count
|
196
|
+
.lastTimestamp
|
197
|
+
.reason
|
198
|
+
.message
|
199
|
+
)
|
200
|
+
|
201
|
+
def self.go_template_for(kind, name)
|
202
|
+
and_conditions = [
|
203
|
+
%[(eq .involvedObject.kind "#{kind}")],
|
204
|
+
%[(eq .involvedObject.name "#{name}")],
|
205
|
+
'(ne .reason "Started")',
|
206
|
+
'(ne .reason "Created")'
|
207
|
+
]
|
208
|
+
condition_start = "{{if and #{and_conditions.join(' ')}}}"
|
209
|
+
field_part = FIELDS.map { |f| "{{#{f}}}" }.join(%({{print "#{FIELD_SEPARATOR}"}}))
|
210
|
+
%({{range .items}}#{condition_start}#{field_part}{{print "#{EVENT_SEPARATOR}"}}{{end}}{{end}})
|
211
|
+
end
|
212
|
+
|
213
|
+
def self.extract_all_from_go_template_blob(blob)
|
214
|
+
blob.split(EVENT_SEPARATOR).map do |event_blob|
|
215
|
+
pieces = event_blob.split(FIELD_SEPARATOR, FIELDS.length)
|
216
|
+
new(
|
217
|
+
subject_kind: pieces[FIELDS.index(".involvedObject.kind")],
|
218
|
+
subject_name: pieces[FIELDS.index(".involvedObject.name")],
|
219
|
+
count: pieces[FIELDS.index(".count")],
|
220
|
+
last_timestamp: pieces[FIELDS.index(".lastTimestamp")],
|
221
|
+
reason: pieces[FIELDS.index(".reason")],
|
222
|
+
message: pieces[FIELDS.index(".message")]
|
223
|
+
)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def initialize(subject_kind:, last_timestamp:, reason:, message:, count:, subject_name:)
|
228
|
+
@subject_kind = subject_kind
|
229
|
+
@subject_name = subject_name
|
230
|
+
@last_timestamp = Time.parse(last_timestamp)
|
231
|
+
@reason = reason
|
232
|
+
@message = message.tr("\n", '')
|
233
|
+
@count = count.to_i
|
234
|
+
end
|
235
|
+
|
236
|
+
def seen_since?(time)
|
237
|
+
time.to_i <= @last_timestamp.to_i
|
238
|
+
end
|
239
|
+
|
240
|
+
def to_s
|
241
|
+
"#{@reason}: #{@message} (#{@count} events)"
|
242
|
+
end
|
243
|
+
end
|
195
244
|
end
|
196
245
|
end
|
@@ -12,38 +12,57 @@ module KubernetesDeploy
|
|
12
12
|
@deploy_started_at = deploy_started_at
|
13
13
|
end
|
14
14
|
|
15
|
-
def run(delay_sync: 3.seconds)
|
16
|
-
delay_sync_until = Time.now.utc
|
15
|
+
def run(delay_sync: 3.seconds, reminder_interval: 30.seconds)
|
16
|
+
delay_sync_until = last_message_logged_at = Time.now.utc
|
17
17
|
|
18
18
|
while @resources.present?
|
19
19
|
if Time.now.utc < delay_sync_until
|
20
20
|
sleep(delay_sync_until - Time.now.utc)
|
21
21
|
end
|
22
|
-
watch_time = (Time.now.utc - @deploy_started_at).round(1)
|
23
22
|
delay_sync_until = Time.now.utc + delay_sync # don't pummel the API if the sync is fast
|
23
|
+
|
24
24
|
@resources.each(&:sync)
|
25
25
|
newly_finished_resources, @resources = @resources.partition(&:deploy_finished?)
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
27
|
+
if newly_finished_resources.present?
|
28
|
+
watch_time = (Time.now.utc - @deploy_started_at).round(1)
|
29
|
+
report_what_just_happened(newly_finished_resources, watch_time)
|
30
|
+
report_what_is_left(reminder: false)
|
31
|
+
last_message_logged_at = Time.now.utc
|
32
|
+
elsif due_for_reminder?(last_message_logged_at, reminder_interval)
|
33
|
+
report_what_is_left(reminder: true)
|
34
|
+
last_message_logged_at = Time.now.utc
|
36
35
|
end
|
36
|
+
end
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
success_string = ColorizedString.new("Successfully deployed in #{watch_time}s:").green
|
40
|
-
@logger.info("#{success_string} #{new_success_list.join(', ')}")
|
41
|
-
end
|
39
|
+
private
|
42
40
|
|
43
|
-
|
44
|
-
|
41
|
+
def report_what_just_happened(resources, watch_time)
|
42
|
+
new_successes, new_failures = resources.partition(&:deploy_succeeded?)
|
43
|
+
new_failures.each do |resource|
|
44
|
+
if resource.deploy_failed?
|
45
|
+
@logger.error("#{resource.id} failed to deploy after #{watch_time}s")
|
46
|
+
else
|
47
|
+
@logger.error("#{resource.id} deployment timed out")
|
45
48
|
end
|
46
49
|
end
|
50
|
+
|
51
|
+
if new_successes.present?
|
52
|
+
success_string = ColorizedString.new("Successfully deployed in #{watch_time}s:").green
|
53
|
+
@logger.info("#{success_string} #{new_successes.map(&:id).join(', ')}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def report_what_is_left(reminder:)
|
58
|
+
return unless @resources.present?
|
59
|
+
resource_list = @resources.map(&:id).join(', ')
|
60
|
+
msg = reminder ? "Still waiting for: #{resource_list}" : "Continuing to wait for: #{resource_list}"
|
61
|
+
@logger.info(msg)
|
62
|
+
end
|
63
|
+
|
64
|
+
def due_for_reminder?(last_message_logged_at, reminder_interval)
|
65
|
+
(last_message_logged_at.to_f + reminder_interval.to_f) <= Time.now.utc.to_f
|
47
66
|
end
|
48
67
|
end
|
49
68
|
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.7.
|
4
|
+
version: 0.7.5
|
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-06-
|
12
|
+
date: 2017-06-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|