helm-wrapper 0.1.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 +7 -0
- data/.gitignore +28 -0
- data/.gitlab-ci.yml +37 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +13 -0
- data/bin/console +16 -0
- data/bin/setup +18 -0
- data/helm-wrapper.gemspec +38 -0
- data/lib/helm-wrapper.rb +59 -0
- data/lib/helm-wrapper/common.rb +27 -0
- data/lib/helm-wrapper/shared.rb +16 -0
- data/lib/helm-wrapper/shared/auths.rb +9 -0
- data/lib/helm-wrapper/shared/auths/azure.rb +176 -0
- data/lib/helm-wrapper/shared/auths/common.rb +91 -0
- data/lib/helm-wrapper/shared/binary.rb +113 -0
- data/lib/helm-wrapper/shared/chart.rb +120 -0
- data/lib/helm-wrapper/shared/config.rb +145 -0
- data/lib/helm-wrapper/shared/latest.rb +79 -0
- data/lib/helm-wrapper/shared/logger.rb +80 -0
- data/lib/helm-wrapper/shared/logging.rb +77 -0
- data/lib/helm-wrapper/shared/runner.rb +250 -0
- data/lib/helm-wrapper/shared/variables.rb +66 -0
- data/lib/helm-wrapper/tasks.rb +11 -0
- data/lib/helm-wrapper/tasks/apply.rb +72 -0
- data/lib/helm-wrapper/tasks/binary.rb +195 -0
- data/lib/helm-wrapper/tasks/destroy.rb +70 -0
- data/lib/helm-wrapper/version.rb +13 -0
- metadata +87 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'net/http'
|
5
|
+
require 'singleton'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
###############################################################################
|
9
|
+
|
10
|
+
module HelmWrapper
|
11
|
+
|
12
|
+
###############################################################################
|
13
|
+
|
14
|
+
module Shared
|
15
|
+
|
16
|
+
###############################################################################
|
17
|
+
|
18
|
+
class Latest
|
19
|
+
|
20
|
+
###############################################################################
|
21
|
+
|
22
|
+
include Singleton
|
23
|
+
|
24
|
+
###############################################################################
|
25
|
+
|
26
|
+
include HelmWrapper::Shared::Logging
|
27
|
+
|
28
|
+
###############################################################################
|
29
|
+
|
30
|
+
@version
|
31
|
+
|
32
|
+
###############################################################################
|
33
|
+
|
34
|
+
def version
|
35
|
+
@version ||= refresh
|
36
|
+
|
37
|
+
return @version
|
38
|
+
end
|
39
|
+
|
40
|
+
###############################################################################
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
###############################################################################
|
45
|
+
|
46
|
+
def refresh
|
47
|
+
logger.info("Finding latest available Helm release...")
|
48
|
+
|
49
|
+
response = Net::HTTP.get_response(URI("https://api.github.com/repos/helm/helm/releases/latest"))
|
50
|
+
|
51
|
+
logger.fatal("GitHub API did not return status 200 for latest version check!") if response.code != "200"
|
52
|
+
logger.fatal("Response body from GitHub API is not permitted!") if not response.class.body_permitted?
|
53
|
+
logger.fatal("Response body from GitHub API is empty!") if response.body.nil?
|
54
|
+
|
55
|
+
body = JSON.parse(response.body)
|
56
|
+
|
57
|
+
logger.fatal("GitHub API JSON response did not include latest available Helm tag name!") if not body.key?("tag_name")
|
58
|
+
logger.fatal("GitHub API indicated the latest available tag name for Helm is blank!") if body["tag_name"].empty?
|
59
|
+
|
60
|
+
version = body["tag_name"]
|
61
|
+
|
62
|
+
logger.success("Latest available Helm release found: #{version}")
|
63
|
+
|
64
|
+
return version
|
65
|
+
end
|
66
|
+
|
67
|
+
###############################################################################
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
###############################################################################
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
###############################################################################
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
###############################################################################
|
@@ -0,0 +1,80 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
###############################################################################
|
6
|
+
|
7
|
+
module HelmWrapper
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
module Shared
|
12
|
+
|
13
|
+
###############################################################################
|
14
|
+
|
15
|
+
class Logger < ::Logger
|
16
|
+
|
17
|
+
###############################################################################
|
18
|
+
|
19
|
+
@colour = false
|
20
|
+
|
21
|
+
###############################################################################
|
22
|
+
|
23
|
+
def colour()
|
24
|
+
@colour
|
25
|
+
end
|
26
|
+
|
27
|
+
###############################################################################
|
28
|
+
|
29
|
+
def colour=(enabled)
|
30
|
+
@colour = [ true, false ].include?(enabled) ? enabled : false
|
31
|
+
end
|
32
|
+
|
33
|
+
###############################################################################
|
34
|
+
|
35
|
+
def success(message)
|
36
|
+
info(format(colour: 32, message: message))
|
37
|
+
end
|
38
|
+
|
39
|
+
###############################################################################
|
40
|
+
|
41
|
+
def warn(message)
|
42
|
+
super(format(colour: 33, message: message))
|
43
|
+
end
|
44
|
+
|
45
|
+
###############################################################################
|
46
|
+
|
47
|
+
def error(message)
|
48
|
+
super(format(colour: 31, message: message))
|
49
|
+
end
|
50
|
+
|
51
|
+
###############################################################################
|
52
|
+
|
53
|
+
def fatal(message)
|
54
|
+
super(format(colour: 31, message: message))
|
55
|
+
exit(1)
|
56
|
+
end
|
57
|
+
|
58
|
+
###############################################################################
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
###############################################################################
|
63
|
+
|
64
|
+
def format(colour: 32, message:)
|
65
|
+
return @colour ? "\e[" + colour.to_s + "m" + message + "\e[0m" : message
|
66
|
+
end
|
67
|
+
|
68
|
+
###############################################################################
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
###############################################################################
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
###############################################################################
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
###############################################################################
|
@@ -0,0 +1,77 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
###############################################################################
|
6
|
+
|
7
|
+
module HelmWrapper
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
module Shared
|
12
|
+
|
13
|
+
###############################################################################
|
14
|
+
|
15
|
+
module Logging
|
16
|
+
|
17
|
+
###############################################################################
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
###############################################################################
|
22
|
+
|
23
|
+
def logger
|
24
|
+
@logger ||= Logging.logger_for(self.class.name)
|
25
|
+
end
|
26
|
+
|
27
|
+
###############################################################################
|
28
|
+
|
29
|
+
@loggers = {}
|
30
|
+
|
31
|
+
###############################################################################
|
32
|
+
|
33
|
+
class << self
|
34
|
+
|
35
|
+
###############################################################################
|
36
|
+
|
37
|
+
def logger_for(classname)
|
38
|
+
@loggers[classname] ||= configure_logger_for(classname)
|
39
|
+
end
|
40
|
+
|
41
|
+
###############################################################################
|
42
|
+
|
43
|
+
def configure_logger_for(classname)
|
44
|
+
colour = ENV["HELM_WRAPPER_LOG_COLOUR"] || "true"
|
45
|
+
level = ENV["HELM_WRAPPER_LOG_LEVEL"] || "INFO"
|
46
|
+
|
47
|
+
logger = ::HelmWrapper::Shared::Logger.new(STDOUT)
|
48
|
+
|
49
|
+
logger.colour = colour.downcase == "true"
|
50
|
+
logger.level = level.upcase
|
51
|
+
logger.progname = classname
|
52
|
+
|
53
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
54
|
+
sevId = severity.chars.first.upcase
|
55
|
+
"[#{sevId}] [#{progname}] #{msg}\n"
|
56
|
+
end
|
57
|
+
|
58
|
+
logger
|
59
|
+
end
|
60
|
+
|
61
|
+
###############################################################################
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
###############################################################################
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
###############################################################################
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
###############################################################################
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
###############################################################################
|
@@ -0,0 +1,250 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
###############################################################################
|
6
|
+
|
7
|
+
module HelmWrapper
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
module Shared
|
12
|
+
|
13
|
+
###############################################################################
|
14
|
+
|
15
|
+
class Runner
|
16
|
+
|
17
|
+
###############################################################################
|
18
|
+
|
19
|
+
include HelmWrapper::Shared::Logging
|
20
|
+
|
21
|
+
###############################################################################
|
22
|
+
|
23
|
+
@@repo_actions = [ "registry", "repo" ]
|
24
|
+
|
25
|
+
###############################################################################
|
26
|
+
|
27
|
+
@auths_attempted = false
|
28
|
+
|
29
|
+
###############################################################################
|
30
|
+
|
31
|
+
attr_reader :auths
|
32
|
+
attr_reader :binary
|
33
|
+
attr_reader :chart
|
34
|
+
attr_reader :config
|
35
|
+
attr_reader :repos
|
36
|
+
|
37
|
+
###############################################################################
|
38
|
+
|
39
|
+
def initialize(binary:, chart:, config:)
|
40
|
+
@binary = binary
|
41
|
+
@chart = chart
|
42
|
+
@config = config
|
43
|
+
|
44
|
+
@auths = false
|
45
|
+
@repos = false
|
46
|
+
end
|
47
|
+
|
48
|
+
###############################################################################
|
49
|
+
|
50
|
+
def init_auths()
|
51
|
+
@auths_attempted = true
|
52
|
+
|
53
|
+
config.auths.map(&:auth)
|
54
|
+
|
55
|
+
@auths = true
|
56
|
+
end
|
57
|
+
|
58
|
+
###############################################################################
|
59
|
+
|
60
|
+
def init_repos(force: false)
|
61
|
+
ENV["HELM_EXPERIMENTAL_OCI"] = "true"
|
62
|
+
|
63
|
+
@chart.oci.each_with_index do |oci_repo, oci_index|
|
64
|
+
logger.info("Logging into OCI repository: #{oci_repo["name"]}")
|
65
|
+
@chart.oci_active(active: true, index: oci_index)
|
66
|
+
|
67
|
+
parameters = Array.new
|
68
|
+
parameters.append("login")
|
69
|
+
parameters.append("\"#{oci_repo["url"]}\"")
|
70
|
+
parameters.append("--username=\"#{oci_repo["username"]}\"")
|
71
|
+
parameters.append("--password-stdin")
|
72
|
+
logger.fatal("Failed to login to Helm OCI repository: #{oci_repo["name"]}, url: #{oci_repo["url"]}") unless run(action: "registry", parameters: parameters, stdin: oci_repo["password"])
|
73
|
+
end
|
74
|
+
|
75
|
+
if @chart.artefact.length > 0 then
|
76
|
+
|
77
|
+
@chart.artefact.each_with_index do |artefact_repo, artefact_index|
|
78
|
+
logger.info("Adding artefact repository: #{artefact_repo["name"]}")
|
79
|
+
@chart.artefact_active(active: true, index: artefact_index)
|
80
|
+
|
81
|
+
parameters = Array.new
|
82
|
+
parameters.append("add")
|
83
|
+
parameters.append("\"#{artefact_repo["name"]}\"")
|
84
|
+
parameters.append("\"#{artefact_repo["url"]}\"")
|
85
|
+
parameters.append("--username=\"#{artefact_repo["username"]}\"") unless artefact_repo["username"].nil?
|
86
|
+
parameters.append("--password=\"#{artefact_repo["password"]}\"") unless artefact_repo["password"].nil?
|
87
|
+
parameters.append("--force-update") if force
|
88
|
+
logger.fatal("Failed to add Helm repository: #{artefact_repo["name"]}, url: #{artefact_repo["url"]}") unless run(action: "repo", parameters: parameters)
|
89
|
+
end
|
90
|
+
|
91
|
+
logger.info("Updating artefact repositories...")
|
92
|
+
logger.fatal("Failed to update Helm artefact repositories!") unless run(action: "repo", parameters: Array.new([ "update" ]))
|
93
|
+
end
|
94
|
+
|
95
|
+
@repos = true
|
96
|
+
end
|
97
|
+
|
98
|
+
###############################################################################
|
99
|
+
|
100
|
+
def clean(repos: true)
|
101
|
+
clean_repos if repos
|
102
|
+
clean_auths if @auths_attempted
|
103
|
+
end
|
104
|
+
|
105
|
+
###############################################################################
|
106
|
+
|
107
|
+
def delete()
|
108
|
+
logger.fatal("Cannot Helm delete before initialising authenticators!") unless auths
|
109
|
+
|
110
|
+
parameters = Array.new
|
111
|
+
parameters.append("--namespace \"#{@config.namespace}\"")
|
112
|
+
parameters.append(@config.release)
|
113
|
+
|
114
|
+
logger.fatal("Helm delete failed!") unless run(action: "delete", parameters: parameters)
|
115
|
+
end
|
116
|
+
|
117
|
+
###############################################################################
|
118
|
+
|
119
|
+
def upgrade(install: true)
|
120
|
+
logger.fatal("Cannot Helm upgrade before initialising authenticators!") unless auths
|
121
|
+
logger.fatal("Cannot Helm upgrade before initialising repositories!") unless repos
|
122
|
+
|
123
|
+
parameters = Array.new
|
124
|
+
parameters.append("--namespace \"#{@config.namespace}\"")
|
125
|
+
parameters.append("--install") if install
|
126
|
+
parameters.append(@config.release)
|
127
|
+
parameters.append(@chart.name)
|
128
|
+
parameters.concat(variable_files)
|
129
|
+
parameters.concat(variable_strings)
|
130
|
+
|
131
|
+
logger.fatal("Helm upgrade failed!") unless run(action: "upgrade", parameters: parameters)
|
132
|
+
end
|
133
|
+
|
134
|
+
###############################################################################
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
###############################################################################
|
139
|
+
|
140
|
+
def clean_auths
|
141
|
+
@auths = false
|
142
|
+
config.auths.map(&:clear)
|
143
|
+
@auths_attempted = false
|
144
|
+
end
|
145
|
+
|
146
|
+
###############################################################################
|
147
|
+
|
148
|
+
def clean_repos
|
149
|
+
@repos = false
|
150
|
+
|
151
|
+
@chart.oci.each do |oci_repo|
|
152
|
+
if oci_repo["active"] then
|
153
|
+
logger.info("Logging out of OCI repository: #{oci_repo["name"]}")
|
154
|
+
|
155
|
+
parameters = Array.new
|
156
|
+
parameters.append("logout")
|
157
|
+
parameters.append("\"#{oci_repo["url"]}\"")
|
158
|
+
logger.error("Failed to logout of Helm OCI repository: #{oci_repo["name"]}, url: #{oci_repo["url"]}") unless run(action: "registry", parameters: parameters)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
@chart.artefact.each do |artefact_repo|
|
163
|
+
if artefact_repo["active"] then
|
164
|
+
if artefact_repo["password"].nil? then
|
165
|
+
logger.info("Not removing artefact repository: #{artefact_repo["name"]}, no credentials stored.")
|
166
|
+
else
|
167
|
+
logger.info("Removing artefact repository: #{artefact_repo["name"]}")
|
168
|
+
|
169
|
+
parameters = Array.new
|
170
|
+
parameters.append("remove")
|
171
|
+
parameters.append("\"#{artefact_repo["name"]}\"")
|
172
|
+
logger.error("Failed to remove Helm repository: #{artefact_repo["name"]}, url: #{artefact_repo["url"]}") unless run(action: "repo", parameters: parameters)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
ENV.delete("HELM_EXPERIMENTAL_OCI")
|
178
|
+
end
|
179
|
+
|
180
|
+
###############################################################################
|
181
|
+
|
182
|
+
def variable_files
|
183
|
+
result = Array.new
|
184
|
+
|
185
|
+
@config.variable_files.each do |variable_file|
|
186
|
+
result.append("--values=\"#{variable_file}\"")
|
187
|
+
end
|
188
|
+
|
189
|
+
return result
|
190
|
+
end
|
191
|
+
|
192
|
+
###############################################################################
|
193
|
+
|
194
|
+
def variable_strings
|
195
|
+
result = Array.new
|
196
|
+
|
197
|
+
result.append("--set=\"config=#{@config.name}\"")
|
198
|
+
|
199
|
+
@config.variables.values.each do |key, value|
|
200
|
+
result.append("--set=\"#{key.to_s}=#{value}\"")
|
201
|
+
end
|
202
|
+
|
203
|
+
return result
|
204
|
+
end
|
205
|
+
|
206
|
+
###############################################################################
|
207
|
+
|
208
|
+
def run(action:, parameters: Array.new, stdin: nil)
|
209
|
+
result = false
|
210
|
+
|
211
|
+
parameters.reject! { |item| not item.kind_of?(String) or item.strip.empty? }
|
212
|
+
|
213
|
+
cmdline = [ "\"#{@binary.path}\"", action ].concat(parameters).join(" ")
|
214
|
+
|
215
|
+
if @@repo_actions.include?(action)
|
216
|
+
begin
|
217
|
+
out, status = Open3.capture2e(cmdline, :stdin_data=>stdin)
|
218
|
+
logger.debug("Helm output:")
|
219
|
+
logger.debug(out)
|
220
|
+
result = status.success?
|
221
|
+
rescue
|
222
|
+
result = false
|
223
|
+
end
|
224
|
+
else
|
225
|
+
logger.info("Starting Helm, action: #{action}")
|
226
|
+
|
227
|
+
fatal("Running Helm with data for stdin can only be used when configuring repos!") unless stdin.nil?
|
228
|
+
puts("\n" + ('#' * 80) + "\n\n")
|
229
|
+
|
230
|
+
result = system(cmdline) || false
|
231
|
+
|
232
|
+
puts("\n" + ('#' * 80) + "\n\n")
|
233
|
+
end
|
234
|
+
|
235
|
+
return result
|
236
|
+
end
|
237
|
+
|
238
|
+
###############################################################################
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
###############################################################################
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
###############################################################################
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
###############################################################################
|