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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +3 -1
- data/lib/vidar.rb +1 -1
- data/lib/vidar/cli.rb +21 -10
- data/lib/vidar/deploy_status.rb +17 -10
- data/lib/vidar/k8s/container_status.rb +28 -9
- data/lib/vidar/k8s/pod_set.rb +72 -0
- data/lib/vidar/log.rb +2 -2
- data/lib/vidar/version.rb +1 -1
- data/vidar.gemspec +1 -0
- metadata +17 -3
- data/lib/vidar/k8s/pods.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbf6458e4bf0f50913580e72f32a2b9fa20dff7d6775a4cf0f3af209f5c7b0a9
|
4
|
+
data.tar.gz: b4fdcdf35ca12932c6a867c18d9f769c58dcad5ad4cc899585cbb2322e0e3db1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd6382056fb7fca1864adf9110a7fea122f20b785ecd590219cbf62968a4ab1f88163955df3c1fd48e185620f429cb89a9b863ac6d82f6087566076d454b897e
|
7
|
+
data.tar.gz: e3a4ff265a97cc941282f20ebd37325530e2af079f432c16f207e295e7c14ea18ae62aeb93fb69ff74c4a5cbd4190b8bed2bd8c9ab8c89827415a73afb7b93e9
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
vidar (0.
|
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
|
data/lib/vidar.rb
CHANGED
data/lib/vidar/cli.rb
CHANGED
@@ -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,
|
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
|
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
|
-
|
123
|
+
deploy_status = Vidar::DeployStatus.new(namespace: Config.get!(:namespace))
|
124
|
+
|
125
|
+
deploy_status.wait_until_completed
|
115
126
|
|
116
|
-
if
|
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
|
data/lib/vidar/deploy_status.rb
CHANGED
@@ -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
|
14
|
-
any_errors = false
|
15
|
+
def wait_until_completed
|
15
16
|
tries = 0
|
16
17
|
|
17
18
|
sleep(INITIAL_SLEEP)
|
18
19
|
|
19
|
-
until
|
20
|
+
until pod_set.deployed?
|
20
21
|
tries += 1
|
21
22
|
sleep(SLEEP)
|
22
|
-
if 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
|
-
|
34
|
+
def last_pod_set
|
35
|
+
@pod_set
|
29
36
|
end
|
30
37
|
|
31
|
-
def
|
32
|
-
|
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
|
-
|
4
|
+
JOB_KIND = "Job".freeze
|
5
|
+
|
6
|
+
attr_reader :data, :state, :namespace, :kind
|
5
7
|
|
6
8
|
def initialize(data)
|
7
|
-
@data
|
8
|
-
@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
|
17
|
-
|
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
|
data/lib/vidar/log.rb
CHANGED
@@ -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(
|
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(
|
13
|
+
puts ColorizedString["#{fill_with} #{text} ".ljust(124, fill_with)].colorize(:light_red)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
data/lib/vidar/version.rb
CHANGED
data/vidar.gemspec
CHANGED
@@ -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.
|
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-
|
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/
|
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
|
data/lib/vidar/k8s/pods.rb
DELETED
@@ -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
|