vidar 0.3.4 → 0.4.0

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
  SHA256:
3
- metadata.gz: 8e85909f2a0b69d1aa3fbaf1e8e88dbe00a65f4464c78206b88affe58d9a0737
4
- data.tar.gz: e9c6deb5b510a19e0f0e24d1f674477f33ce072f07117757b098d13ed20dbd08
3
+ metadata.gz: fbf6458e4bf0f50913580e72f32a2b9fa20dff7d6775a4cf0f3af209f5c7b0a9
4
+ data.tar.gz: b4fdcdf35ca12932c6a867c18d9f769c58dcad5ad4cc899585cbb2322e0e3db1
5
5
  SHA512:
6
- metadata.gz: c8f6d696c5d58262473dd8a62b96cd942d8246de5165e5477be70f3b4dfd371b9f4a86da597534026d2beaeafe249d223cb4963837d5e820a88dc3ab9fcd365e
7
- data.tar.gz: 426f39c791e5cabb442f1a5a433c0bce5849cc4fb2cf59c82ba446b66e8528bafe3e714c525af5dabe7a4d2bbf1a6c0e3a9dbe0fb34c108b0cdda5fb2f3938c5
6
+ metadata.gz: cd6382056fb7fca1864adf9110a7fea122f20b785ecd590219cbf62968a4ab1f88163955df3c1fd48e185620f429cb89a9b863ac6d82f6087566076d454b897e
7
+ data.tar.gz: e3a4ff265a97cc941282f20ebd37325530e2af079f432c16f207e295e7c14ea18ae62aeb93fb69ff74c4a5cbd4190b8bed2bd8c9ab8c89827415a73afb7b93e9
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
 
13
13
  # Cached rubocop config files
14
14
  .rubocop-http*
15
+ vidar.yml
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vidar (0.3.4)
4
+ vidar (0.4.0)
5
5
  colorize
6
6
  faraday
7
7
  thor (~> 0.20)
@@ -10,6 +10,7 @@ GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
12
  ast (2.4.0)
13
+ awesome_print (1.8.0)
13
14
  coderay (1.1.2)
14
15
  colorize (0.8.1)
15
16
  diff-lcs (1.3)
@@ -56,6 +57,7 @@ PLATFORMS
56
57
  ruby
57
58
 
58
59
  DEPENDENCIES
60
+ awesome_print
59
61
  bundler
60
62
  pry
61
63
  rake
@@ -14,7 +14,7 @@ require 'vidar/log'
14
14
  require 'vidar/run'
15
15
  require 'vidar/slack_notification'
16
16
  require 'vidar/k8s/container_status'
17
- require 'vidar/k8s/pods'
17
+ require 'vidar/k8s/pod_set'
18
18
  require 'vidar/deploy_status'
19
19
  require 'vidar/cli'
20
20
 
@@ -59,14 +59,11 @@ module Vidar
59
59
  end
60
60
 
61
61
  desc "deploy", "Performs k8s deployment with deploy hook"
62
- method_option :revision, default: nil
62
+ method_option :revision, required: false
63
63
  def deploy
64
64
  revision = options[:revision] || Config.get!(:revision)
65
65
  Log.info "Current cluster_name: #{Config.get!(:cluster_name)} ###"
66
66
 
67
- Log.info "Set kubectl image..."
68
- Run.kubectl "set image deployments,cronjobs *=#{Config.get!(:image)}:#{revision} --all"
69
-
70
67
  Log.info "Looking for deploy hook..."
71
68
  template_name, error, status = Open3.capture3 "kubectl get cronjob deploy-hook-template -n #{Config.get!(:namespace)} -o name --ignore-not-found=true"
72
69
 
@@ -76,12 +73,24 @@ module Vidar
76
73
  else
77
74
  Log.info "Executing deploy hook #{template_name.strip!}..."
78
75
  Run.kubectl "delete job deploy-hook --ignore-not-found=true"
76
+ Run.kubectl "set image cronjobs deploy-hook-template=#{Config.get!(:image)}:#{revision} --all"
79
77
  Run.kubectl "create job deploy-hook --from=#{template_name}"
78
+
79
+ deploy_status = Vidar::DeployStatus.new(namespace: Config.get!(:namespace), filter: "deploy-hook")
80
+ deploy_status.wait_until_completed
81
+
82
+ unless deploy_status.success?
83
+ Log.error "Error running deploy hook template"
84
+ exit(1)
85
+ end
80
86
  end
81
87
  else
82
88
  Log.info "Error getting deploy hook template: #{error}"
83
89
  exit(1)
84
90
  end
91
+
92
+ Log.info "Set kubectl image..."
93
+ Run.kubectl "set image deployments,cronjobs *=#{Config.get!(:image)}:#{revision} --all"
85
94
  end
86
95
 
87
96
  desc "release", "Builds and publishes docker images"
@@ -97,11 +106,11 @@ module Vidar
97
106
  method_option :success_color, required: false
98
107
  method_option :error_color, required: false
99
108
  def monitor_deploy_status
100
- Log.info "Current cluster_name: #{Config.get!(:cluster_name)} ###"
109
+ Log.info "Current cluster_name: #{Config.get!(:cluster_name)}"
101
110
  Log.info "Checking is all containers on #{Config.get!(:cluster_name)} in #{Config.get!(:namespace)} are ready..."
102
111
 
103
112
  slack_notification = SlackNotification.new(
104
- webhook_url: Config.get!(:slack_webhook_url),
113
+ webhook_url: Config.get(:slack_webhook_url),
105
114
  github: Config.get!(:github),
106
115
  revision: Config.get!(:revision),
107
116
  revision_name: Config.get!(:revision_name),
@@ -111,13 +120,15 @@ module Vidar
111
120
  error_color: options[:error_color],
112
121
  )
113
122
 
114
- ok = Vidar::DeployStatus.new(Config.get!(:namespace)).ok?
123
+ deploy_status = Vidar::DeployStatus.new(namespace: Config.get!(:namespace))
124
+
125
+ deploy_status.wait_until_completed
115
126
 
116
- if ok
117
- Log.info "OK: All containers are ready."
127
+ if deploy_status.success?
128
+ Log.info "OK: All containers are ready"
118
129
  slack_notification.success if slack_notification.configured?
119
130
  else
120
- Log.error "ERROR: Some of containers are not ready."
131
+ Log.error "ERROR: Some of containers are errored or not ready"
121
132
  slack_notification.error if slack_notification.configured?
122
133
  exit(1)
123
134
  end
@@ -4,32 +4,39 @@ module Vidar
4
4
  SLEEP = 10
5
5
  MAX_TRIES = 30
6
6
 
7
- attr_reader :namespace
7
+ attr_reader :namespace, :filter, :max_tries
8
8
 
9
- def initialize(namespace)
9
+ def initialize(namespace:, filter: nil, max_tries: MAX_TRIES)
10
10
  @namespace = namespace
11
+ @filter = filter
12
+ @max_tries = max_tries
11
13
  end
12
14
 
13
- def error?
14
- any_errors = false
15
+ def wait_until_completed
15
16
  tries = 0
16
17
 
17
18
  sleep(INITIAL_SLEEP)
18
19
 
19
- until K8s::Pods.new(namespace).all_ready?
20
+ until pod_set.deployed?
20
21
  tries += 1
21
22
  sleep(SLEEP)
22
- if tries > MAX_TRIES
23
- any_errors = true
23
+ if tries > max_tries
24
24
  break
25
25
  end
26
26
  end
27
+ end
28
+
29
+ def success?
30
+ return false unless last_pod_set
31
+ last_pod_set.success?
32
+ end
27
33
 
28
- any_errors
34
+ def last_pod_set
35
+ @pod_set
29
36
  end
30
37
 
31
- def ok?
32
- !error?
38
+ def pod_set
39
+ @pod_set = K8s::PodSet.new(namespace: namespace, filter: filter)
33
40
  end
34
41
  end
35
42
  end
@@ -1,20 +1,31 @@
1
1
  module Vidar
2
2
  module K8s
3
3
  class ContainerStatus
4
- attr_reader :data, :state, :namespace
4
+ JOB_KIND = "Job".freeze
5
+
6
+ attr_reader :data, :state, :namespace, :kind
5
7
 
6
8
  def initialize(data)
7
- @data = data
8
- @state = data["state"]
9
+ @data = data
10
+ @state = data["state"]
9
11
  @namespace = data["namespace"]
12
+ @kind = data["kind"]
10
13
  end
11
14
 
12
15
  def name
13
16
  data["name"]
14
17
  end
15
18
 
16
- def ok?
17
- (ready? && running?) || terminated_completed?
19
+ def deployed?
20
+ return terminated? if job?
21
+
22
+ ready? && running?
23
+ end
24
+
25
+ def success?
26
+ return terminated_completed? if job?
27
+
28
+ ready? && running?
18
29
  end
19
30
 
20
31
  def print
@@ -37,13 +48,13 @@ module Vidar
37
48
  [ColorizedString["Not ready"].light_red, "Started at: #{running_started_at}"]
38
49
  end
39
50
  elsif terminated_completed?
40
- [ColorizedString["Terminated/Completed"].light_green, "Finished at: #{terminated_finished_at}"]
51
+ [ColorizedString["Terminated/Completed"].light_green, terminated_finished_at ? "Finished at: #{terminated_finished_at}" : ""]
41
52
  elsif terminated_error?
42
- [ColorizedString["Terminated/Error"].light_red]
53
+ [ColorizedString["Terminated/Error"].light_red, ""]
43
54
  elsif waiting?
44
- [ColorizedString["Waiting"].light_green]
55
+ [ColorizedString["Waiting"].light_green, ""]
45
56
  else
46
- [ColorizedString[state.inspect].light_red]
57
+ [ColorizedString[state.inspect].light_red, ""]
47
58
  end
48
59
  end
49
60
 
@@ -63,6 +74,10 @@ module Vidar
63
74
  state.dig("running", "startedAt")
64
75
  end
65
76
 
77
+ def terminated?
78
+ !state["terminated"].nil?
79
+ end
80
+
66
81
  def terminated_completed?
67
82
  state.dig("terminated", "reason") == "Completed" || state.dig("terminated", "exitCode") == 0
68
83
  end
@@ -74,6 +89,10 @@ module Vidar
74
89
  def terminated_error?
75
90
  state.dig("terminated", "reason") == "Error" || state.dig("terminated", "exitCode")
76
91
  end
92
+
93
+ def job?
94
+ kind == JOB_KIND
95
+ end
77
96
  end
78
97
  end
79
98
  end
@@ -0,0 +1,72 @@
1
+ module Vidar
2
+ module K8s
3
+ class PodSet
4
+ def initialize(namespace:, filter: nil)
5
+ @namespace = namespace
6
+ @filter = filter
7
+ end
8
+
9
+ def deployed?
10
+ if items.empty?
11
+ Log.error "Could not fetch pod list"
12
+ return false
13
+ end
14
+
15
+ Log.line
16
+
17
+ container_statuses.each(&:print)
18
+
19
+ Log.line
20
+
21
+ container_statuses.all?(&:deployed?)
22
+ end
23
+
24
+ def success?
25
+ container_statuses.all?(&:success?)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :namespace, :filter
31
+
32
+ def items
33
+ @items ||= begin
34
+ json = JSON.parse(kubectl_get.strip)
35
+ json["items"] || []
36
+ end
37
+ end
38
+
39
+ def kubectl_get
40
+ if namespace == "all"
41
+ `kubectl get pods --all-namespaces -o json`
42
+ else
43
+ `kubectl get pods -n #{namespace} -o json`
44
+ end
45
+ end
46
+
47
+ def container_statuses
48
+ return all_container_statuses unless filter
49
+
50
+ all_container_statuses.select { |cs| cs.name.to_s.include?(filter) }
51
+ end
52
+
53
+ def all_container_statuses
54
+ @all_container_statuses ||= container_statuses_data.map { |status| ContainerStatus.new(status) }
55
+ end
56
+
57
+ def container_statuses_data
58
+ items.map do |i|
59
+ owner_references = i.dig("metadata", "ownerReferences") || []
60
+ kind = (owner_references[0] || {})["kind"]
61
+ namespace = i.dig("metadata", "namespace")
62
+ statuses = i.dig("status", "containerStatuses") || []
63
+ statuses.each do |s|
64
+ s["namespace"] = namespace
65
+ s["kind"] = kind
66
+ end
67
+ statuses
68
+ end.flatten
69
+ end
70
+ end
71
+ end
72
+ end
@@ -6,11 +6,11 @@ module Vidar
6
6
  end
7
7
 
8
8
  def info(text, fill_with = "#")
9
- puts ColorizedString["#{fill_with} #{text} ".ljust(100, fill_with)].colorize(:light_green)
9
+ puts ColorizedString["#{fill_with} #{text} ".ljust(124, fill_with)].colorize(:light_green)
10
10
  end
11
11
 
12
12
  def error(text, fill_with = "#")
13
- puts ColorizedString["#{fill_with} #{text} ".ljust(100, fill_with)].colorize(:light_red)
13
+ puts ColorizedString["#{fill_with} #{text} ".ljust(124, fill_with)].colorize(:light_red)
14
14
  end
15
15
  end
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module Vidar
2
- VERSION = '0.3.4'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency 'faraday'
29
29
  spec.add_dependency 'thor', '~> 0.20'
30
30
 
31
+ spec.add_development_dependency 'awesome_print'
31
32
  spec.add_development_dependency 'bundler'
32
33
  spec.add_development_dependency 'pry'
33
34
  spec.add_development_dependency 'rake'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vidar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Knapik
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-09-30 00:00:00.000000000 Z
12
+ date: 2019-10-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colorize
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0.20'
56
+ - !ruby/object:Gem::Dependency
57
+ name: awesome_print
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: bundler
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -166,7 +180,7 @@ files:
166
180
  - lib/vidar/deploy_status.rb
167
181
  - lib/vidar/interpolation.rb
168
182
  - lib/vidar/k8s/container_status.rb
169
- - lib/vidar/k8s/pods.rb
183
+ - lib/vidar/k8s/pod_set.rb
170
184
  - lib/vidar/log.rb
171
185
  - lib/vidar/run.rb
172
186
  - lib/vidar/slack_notification.rb
@@ -1,56 +0,0 @@
1
- module Vidar
2
- module K8s
3
- class Pods
4
- def initialize(namespace)
5
- @namespace = namespace
6
- end
7
-
8
- def all_ready?
9
- if items.empty?
10
- Log.error "Could not fetch pod list"
11
- return false
12
- end
13
-
14
- Log.line
15
-
16
- container_statuses.each(&:print)
17
-
18
- Log.line
19
-
20
- container_statuses.all?(&:ok?)
21
- end
22
-
23
- private
24
-
25
- attr_reader :namespace
26
-
27
- def items
28
- @items ||= begin
29
- json = JSON.parse(kubectl_get.strip)
30
- json["items"] || []
31
- end
32
- end
33
-
34
- def kubectl_get
35
- if namespace == 'all'
36
- `kubectl get pods --all-namespaces -o json`
37
- else
38
- `kubectl get pods -n #{namespace} -o json`
39
- end
40
- end
41
-
42
- def container_statuses
43
- @container_statuses ||= container_statuses_data.map { |status| ContainerStatus.new(status) }
44
- end
45
-
46
- def container_statuses_data
47
- items.map do |i|
48
- namespace = i.dig("metadata", "namespace")
49
- statuses = i.dig("status", "containerStatuses") || []
50
- statuses.each { |s| s["namespace"] = namespace }
51
- statuses
52
- end.flatten
53
- end
54
- end
55
- end
56
- end