vidar 0.3.4 → 0.4.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 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