kubernetes-deploy 0.7.4 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 255ea8b3ecd484e3867da8b34b4a61a927d99c1f
4
- data.tar.gz: 79c4034b3460995f65fbeb54216688a5b1f448b6
3
+ metadata.gz: 8974c6df435df28dab80164ebdea271275813e2b
4
+ data.tar.gz: a4d53b653bb5cfa44307f92f865bcdf08a5c1540
5
5
  SHA512:
6
- metadata.gz: 8c9b9c54dea86318add19d23123e00ec5f3195488ec0ecbf954cdfe126dd1ca780d2c7cea6687342f2df8410ef7c5a53fd8b3ebb0649b6e8488fb1f2be42f0ef
7
- data.tar.gz: a2cc7698a3b9f9b66bf8a54b7c5ac2483946760cdb52612c8b73fbc3c57ad8f716e8cedb4e1a732ecda59a82f37815de4ba41eb212a1e75399bd461b06061ebc
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
- # {"subject_kind" => "Pod", "some" => "stuff"}, # event 1
158
- # {"subject_kind" => "Pod", "other" => "stuff"}, # event 2
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
- fields = "{.involvedObject.kind}\t{.count}\t{.message}\t{.reason}"
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
- out.split("\n").each_with_object(event_collector) do |event_blob, events|
170
- pieces = event_blob.split("\t")
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
- new_success_list = []
28
- newly_finished_resources.each do |resource|
29
- if resource.deploy_failed?
30
- @logger.error("#{resource.id} failed to deploy after #{watch_time}s")
31
- elsif resource.deploy_timed_out?
32
- @logger.error("#{resource.id} deployment timed out")
33
- else
34
- new_success_list << resource.id
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
- unless new_success_list.empty?
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
- if newly_finished_resources.present? && @resources.present? # something happened this cycle, more to go
44
- @logger.info("Continuing to wait for: #{@resources.map(&:id).join(', ')}")
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
@@ -1,3 +1,3 @@
1
1
  module KubernetesDeploy
2
- VERSION = "0.7.4"
2
+ VERSION = "0.7.5"
3
3
  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
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-05 00:00:00.000000000 Z
12
+ date: 2017-06-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport