minfra-cli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +12 -0
  3. data/.gitignore +16 -0
  4. data/.rspec +2 -0
  5. data/CHANGELOG.md +2 -0
  6. data/Dockerfile +12 -0
  7. data/bin/build +20 -0
  8. data/bin/console +16 -0
  9. data/bin/container_exec +9 -0
  10. data/bin/run_tests +74 -0
  11. data/bin/setup.sh +22 -0
  12. data/exe/minfra +6 -0
  13. data/lib/deep_merge.rb +149 -0
  14. data/lib/hash.rb +28 -0
  15. data/lib/minfra/cli/ask.rb +43 -0
  16. data/lib/minfra/cli/command.rb +35 -0
  17. data/lib/minfra/cli/commands/dev.rb +54 -0
  18. data/lib/minfra/cli/commands/kube.rb +279 -0
  19. data/lib/minfra/cli/commands/project/branch.rb +17 -0
  20. data/lib/minfra/cli/commands/project/tag.rb +40 -0
  21. data/lib/minfra/cli/commands/project.rb +113 -0
  22. data/lib/minfra/cli/commands/setup.rb +49 -0
  23. data/lib/minfra/cli/commands/stack/app_template.rb +65 -0
  24. data/lib/minfra/cli/commands/stack/client_template.rb +36 -0
  25. data/lib/minfra/cli/commands/stack/kube_stack_template.rb +94 -0
  26. data/lib/minfra/cli/commands/stack.rb +120 -0
  27. data/lib/minfra/cli/commands/tag.rb +86 -0
  28. data/lib/minfra/cli/common.rb +41 -0
  29. data/lib/minfra/cli/config.rb +111 -0
  30. data/lib/minfra/cli/document.rb +19 -0
  31. data/lib/minfra/cli/hook.rb +65 -0
  32. data/lib/minfra/cli/logging.rb +26 -0
  33. data/lib/minfra/cli/main_command.rb +32 -0
  34. data/lib/minfra/cli/plugins.rb +34 -0
  35. data/lib/minfra/cli/runner.rb +59 -0
  36. data/lib/minfra/cli/templater.rb +63 -0
  37. data/lib/minfra/cli/version.rb +5 -0
  38. data/lib/minfra/cli.rb +80 -0
  39. data/lib/orchparty/ast.rb +53 -0
  40. data/lib/orchparty/cli.rb +69 -0
  41. data/lib/orchparty/context.rb +22 -0
  42. data/lib/orchparty/dsl_parser.rb +229 -0
  43. data/lib/orchparty/dsl_parser_kubernetes.rb +361 -0
  44. data/lib/orchparty/kubernetes_application.rb +305 -0
  45. data/lib/orchparty/plugin.rb +24 -0
  46. data/lib/orchparty/plugins/env.rb +41 -0
  47. data/lib/orchparty/transformations/all.rb +18 -0
  48. data/lib/orchparty/transformations/mixin.rb +73 -0
  49. data/lib/orchparty/transformations/remove_internal.rb +16 -0
  50. data/lib/orchparty/transformations/sort.rb +10 -0
  51. data/lib/orchparty/transformations/variable.rb +56 -0
  52. data/lib/orchparty/transformations.rb +24 -0
  53. data/lib/orchparty/version.rb +3 -0
  54. data/lib/orchparty.rb +59 -0
  55. data/minfra-cli.gemspec +40 -0
  56. data/project.json +7 -0
  57. data/templates/kind.yaml.erb +33 -0
  58. data/templates/kube_config.yaml.erb +7 -0
  59. data/templates/minfra_config.json.erb +26 -0
  60. metadata +196 -0
@@ -0,0 +1,361 @@
1
+ require 'pathname'
2
+ require 'securerandom'
3
+ module Orchparty
4
+ module Kubernetes
5
+ class DSLParser
6
+ attr_reader :filename
7
+
8
+ def initialize(filename)
9
+ @filename = filename
10
+ end
11
+
12
+ def parse
13
+ file_content = File.read(filename)
14
+ builder = RootBuilder.new
15
+ builder.instance_eval(file_content, filename)
16
+ builder._build
17
+ end
18
+ end
19
+
20
+ class Builder
21
+ def self.build(*args, block)
22
+ builder = self.new(*args)
23
+ builder.instance_eval(&block) if block
24
+ builder._build
25
+ end
26
+
27
+ def assign_or_merge(node, key, value)
28
+ if node[key]
29
+ node[key] = node[key].deep_merge_concat(value)
30
+ else
31
+ node[key] = value
32
+ end
33
+ end
34
+ end
35
+
36
+ class RootBuilder < Builder
37
+
38
+ def initialize
39
+ @root = AST.root
40
+ end
41
+
42
+ def import(rel_file)
43
+ old_file_path = Pathname.new(caller[0][/[^:]+/]).parent
44
+ rel_file_path = Pathname.new rel_file
45
+ new_file_path = old_file_path + rel_file_path
46
+ file_content = File.read(new_file_path)
47
+ instance_eval(file_content, new_file_path.expand_path.to_s)
48
+ end
49
+
50
+ def application(name, &block)
51
+ @root.applications[name] = ApplicationBuilder.build(name, block)
52
+ self
53
+ end
54
+
55
+ def mixin(name, &block)
56
+ @root._mixins[name] = MixinBuilder.build(name, block)
57
+ self
58
+ end
59
+
60
+ def _build
61
+ @root
62
+ end
63
+ end
64
+
65
+ class MixinBuilder < Builder
66
+
67
+ def initialize(name)
68
+ @mixin = AST.mixin(name: name)
69
+ end
70
+
71
+ def template(path)
72
+ chart_name = "_mixin_temp_name"
73
+ unless @mixin.services[chart_name]
74
+ @mixin.services[chart_name] = AST.chart(name: chart_name, _type: "chart" )
75
+ @mixin._service_order << chart_name
76
+ end
77
+ chart = @mixin.services[chart_name]
78
+ chart.template = path
79
+ self
80
+ end
81
+
82
+ def service(name, &block)
83
+
84
+ chart_name = "_mixin_temp_name"
85
+ unless @mixin.services[chart_name]
86
+ @mixin.services[chart_name] = AST.chart(name: chart_name, _type: "chart" )
87
+ @mixin._service_order << chart_name
88
+ end
89
+ chart = @mixin.services[chart_name]
90
+
91
+ result = ServiceBuilder.build(name, "chart-service", block)
92
+
93
+ name = "chart-#{chart.name}-#{name}"
94
+ @mixin.services[name] = result
95
+ @mixin._service_order << name
96
+ chart._services << name
97
+ self
98
+ end
99
+
100
+ def helm(name, &block)
101
+ result = ServiceBuilder.build(name, "helm", block)
102
+ @mixin.services[name] = result
103
+ @mixin._mixins[name] = result
104
+ self
105
+ end
106
+
107
+
108
+ def apply(name, &block)
109
+ result = ServiceBuilder.build(name, "apply", block)
110
+ @mixin.services[name] = result
111
+ @mixin._mixins[name] = result
112
+ self
113
+ end
114
+
115
+ def mixin(name, &block)
116
+ @mixin._mixins[name] = ServiceMixinBuilder.build(name, block)
117
+ end
118
+
119
+ def volumes(&block)
120
+ @mixin.volumes = HashBuilder.build(block)
121
+ end
122
+
123
+ def networks(&block)
124
+ @mixin.networks = HashBuilder.build(block)
125
+ end
126
+
127
+ def _build
128
+ @mixin
129
+ end
130
+ end
131
+
132
+ class ApplicationBuilder < Builder
133
+
134
+ def initialize(name)
135
+ @application = AST.application(name: name)
136
+ end
137
+
138
+ def mix(name)
139
+ @application._mix << name
140
+ end
141
+
142
+ def mixin(name, &block)
143
+ @application._mixins[name] = ApplicationMixinBuilder.build(block)
144
+ self
145
+ end
146
+
147
+ def all(&block)
148
+ @application.all = AllBuilder.build(block)
149
+ self
150
+ end
151
+
152
+ def variables(&block)
153
+ @application._variables = VariableBuilder.build(block)
154
+ self
155
+ end
156
+
157
+ def volumes(&block)
158
+ @application.volumes = HashBuilder.build(block)
159
+ self
160
+ end
161
+
162
+ def helm(name, &block)
163
+ result = ServiceBuilder.build(name, "helm", block)
164
+ @application.services[name] = result
165
+ @application._service_order << name
166
+ self
167
+ end
168
+
169
+ def label(&block)
170
+ name = SecureRandom.hex
171
+ result = ServiceWithoutNameBuilder.build("label", block)
172
+ @application.services[name] = result
173
+ @application._service_order << name
174
+ self
175
+ end
176
+
177
+ def apply(name, &block)
178
+ result = ServiceBuilder.build(name, "apply", block)
179
+ @application.services[name] = result
180
+ @application._service_order << name
181
+ self
182
+ end
183
+
184
+ def secret_generic(name, &block)
185
+ result = ServiceBuilder.build(name, "secret_generic", block)
186
+ @application.services[name] = result
187
+ @application._service_order << name
188
+ self
189
+ end
190
+
191
+ def wait(&block)
192
+ name = SecureRandom.hex
193
+ result = ServiceBuilder.build(name, "wait", block)
194
+ @application.services[name] = result
195
+ @application._service_order << name
196
+ self
197
+ end
198
+
199
+ def chart(name, &block)
200
+ @application.services[name] = ChartBuilder.build(name, @application, "chart", block)
201
+ @application._service_order << name
202
+ self
203
+ end
204
+
205
+ def template(path)
206
+ chart_name = @application.name
207
+ unless @application.services[chart_name]
208
+ @application.services[chart_name] = AST.chart(name: chart_name, _type: "chart" )
209
+ @application._service_order << chart_name
210
+ end
211
+ chart = @application.services[chart_name]
212
+ chart.template = path
213
+ self
214
+ end
215
+
216
+ def service(name, &block)
217
+
218
+ chart_name = @application.name
219
+ unless @application.services[chart_name]
220
+ @application.services[chart_name] = AST.chart(name: chart_name, _type: "chart" )
221
+ @application._service_order << chart_name
222
+ end
223
+ chart = @application.services[chart_name]
224
+
225
+ result = ServiceBuilder.build(name, "chart-service", block)
226
+
227
+ name = "chart-#{chart.name}-#{name}"
228
+ @application.services[name] = result
229
+ @application._service_order << name
230
+ chart._services << name
231
+ self
232
+ end
233
+
234
+ def _build
235
+ @application
236
+ end
237
+ end
238
+
239
+ class HashBuilder < Builder
240
+
241
+ def method_missing(_, *values, &block)
242
+ if block_given?
243
+ value = HashBuilder.build(block)
244
+ if values.count == 1
245
+ @hash ||= AST.hash
246
+ @hash[values.first.to_sym] = value
247
+ else
248
+ @hash ||= AST.array
249
+ @hash << value
250
+ end
251
+ else
252
+ value = values.first
253
+ if value.is_a? Hash
254
+ @hash ||= AST.hash
255
+ key, value = value.first
256
+ begin
257
+ @hash[key.to_sym] = value
258
+ rescue
259
+ warn "Problem with key: #{key} #{value}"
260
+ raise
261
+ end
262
+
263
+ else
264
+ @hash ||= AST.array
265
+ @hash << value
266
+ end
267
+ end
268
+ self
269
+ end
270
+
271
+ def _build
272
+ @hash
273
+ end
274
+ end
275
+
276
+ class VariableBuilder < HashBuilder
277
+ def _build
278
+ super || {}
279
+ end
280
+ end
281
+
282
+ class CommonBuilder < Builder
283
+
284
+ def initialize(node)
285
+ @node = node
286
+ end
287
+
288
+ def mix(name)
289
+ @node._mix << name
290
+ end
291
+
292
+ def method_missing(name, *values, &block)
293
+ if block_given?
294
+ assign_or_merge(@node, name, HashBuilder.build(block))
295
+ else
296
+ assign_or_merge(@node, name, values.first)
297
+ end
298
+ end
299
+
300
+ def _build
301
+ @node
302
+ end
303
+
304
+ def variables(&block)
305
+ @node._variables ||= {}
306
+ @node._variables = @node._variables.merge(VariableBuilder.build(block))
307
+ self
308
+ end
309
+ end
310
+
311
+ class AllBuilder < CommonBuilder
312
+ def initialize
313
+ super AST.all
314
+ end
315
+ end
316
+
317
+ class ApplicationMixinBuilder < CommonBuilder
318
+ def initialize
319
+ super AST.application_mixin
320
+ end
321
+ end
322
+
323
+ class ServiceWithoutNameBuilder < CommonBuilder
324
+
325
+ def initialize( type)
326
+ super AST.service(_type: type)
327
+ end
328
+ end
329
+
330
+ class ServiceBuilder < CommonBuilder
331
+
332
+ def initialize(name, type)
333
+ super AST.service(name: name, _type: type)
334
+ end
335
+ end
336
+
337
+ class ServiceMixinBuilder < CommonBuilder
338
+
339
+ def initialize(name)
340
+ super AST.service(name: name)
341
+ end
342
+ end
343
+
344
+ class ChartBuilder < CommonBuilder
345
+ def initialize(name, application, type)
346
+ super AST.chart(name: name, _type: type )
347
+ @application = application
348
+ end
349
+
350
+ def service(name, &block)
351
+ result = ServiceBuilder.build(name, "chart-service", block)
352
+
353
+ name = "chart-#{@node.name}-#{name}"
354
+ @application.services[name] = result
355
+ @application._service_order << name
356
+ @node._services << name
357
+ self
358
+ end
359
+ end
360
+ end
361
+ end
@@ -0,0 +1,305 @@
1
+ require 'erb'
2
+ require 'erubis'
3
+ require 'open3'
4
+ require 'ostruct'
5
+ require 'yaml'
6
+ require 'tempfile'
7
+ require 'active_support'
8
+ require 'active_support/core_ext'
9
+
10
+ module Orchparty
11
+ module Services
12
+ class Context
13
+ attr_accessor :cluster_name
14
+ attr_accessor :namespace
15
+ attr_accessor :dir_path
16
+ attr_accessor :app_config
17
+ attr_accessor :options
18
+
19
+ def initialize(cluster_name: , namespace:, file_path: , app_config:, out_io: STDOUT)
20
+ self.cluster_name = cluster_name
21
+ self.namespace = namespace
22
+ self.dir_path = file_path
23
+ self.app_config = app_config
24
+ @out_io = out_io
25
+ self.options=options
26
+ end
27
+
28
+ def template(file_path, helm, flag: "-f ", fix_file_path: nil)
29
+ return "" unless file_path
30
+ puts "Rendering: #{file_path}"
31
+ file_path = File.join(self.dir_path, file_path)
32
+ if(file_path.end_with?(".erb"))
33
+ helm.application = OpenStruct.new(cluster_name: cluster_name, namespace: namespace)
34
+ template = Erubis::Eruby.new(File.read(file_path))
35
+ yaml = template.result(helm.get_binding)
36
+ file = Tempfile.new("kube-deploy.yaml")
37
+ file.write(yaml)
38
+ file.close
39
+ file_path = file.path
40
+ end
41
+ "#{flag}#{fix_file_path || file_path}"
42
+ end
43
+
44
+ def print_install(helm)
45
+ @out_io.puts "---"
46
+ @out_io.puts install_cmd(helm, value_path(helm))
47
+ @out_io.puts upgrade_cmd(helm, value_path(helm))
48
+ @out_io.puts "---"
49
+ @out_io.puts File.read(template(value_path(helm), helm, flag: "")) if value_path(helm)
50
+ end
51
+
52
+ # On 05.02.2021 we have decided that it would be best to print both commands.
53
+ # This way it would be possible to debug both upgrade and install and also people would not see git diffs all the time.
54
+ def print_upgrade(helm)
55
+ print_install(helm)
56
+ end
57
+
58
+ def upgrade(helm)
59
+ @out_io.puts system(upgrade_cmd(helm))
60
+ end
61
+
62
+ def install(helm)
63
+ @out_io.puts system(install_cmd(helm))
64
+ end
65
+ end
66
+
67
+ class Helm < Context
68
+ def value_path(helm)
69
+ helm[:values]
70
+ end
71
+
72
+ def upgrade_cmd(helm, fix_file_path = nil)
73
+ "helm upgrade --namespace #{namespace} --kube-context #{cluster_name} --version #{helm.version} #{helm.name} #{helm.chart} #{template(value_path(helm), helm, fix_file_path: fix_file_path)}"
74
+ end
75
+
76
+ def install_cmd(helm, fix_file_path = nil)
77
+ "helm install --create-namespace --namespace #{namespace} --kube-context #{cluster_name} --version #{helm.version} #{helm.name} #{helm.chart} #{template(value_path(helm), helm, fix_file_path: fix_file_path)}"
78
+ end
79
+ end
80
+
81
+ class Apply < Context
82
+ def value_path(apply)
83
+ apply[:name]
84
+ end
85
+
86
+ def upgrade_cmd(apply, fix_file_path = nil)
87
+ "kubectl apply --namespace #{namespace} --context #{cluster_name} #{template(value_path(apply), apply, fix_file_path: fix_file_path)}"
88
+ end
89
+
90
+ def install_cmd(apply, fix_file_path = nil)
91
+ "kubectl apply --namespace #{namespace} --context #{cluster_name} #{template(value_path(apply), apply, fix_file_path: fix_file_path)}"
92
+ end
93
+ end
94
+
95
+ class SecretGeneric < Context
96
+ def value_path(secret)
97
+ secret[:from_file]
98
+ end
99
+
100
+ def upgrade_cmd(secret, fix_file_path=nil)
101
+ "kubectl --namespace #{namespace} --context #{cluster_name} create secret generic --dry-run -o yaml #{secret[:name]} #{template(value_path(secret), secret, flag: "--from-file=", fix_file_path: fix_file_path)} | kubectl --context #{cluster_name} apply -f -"
102
+ end
103
+
104
+ def install_cmd(secret, fix_file_path=nil)
105
+ "kubectl --namespace #{namespace} --context #{cluster_name} create secret generic --dry-run -o yaml #{secret[:name]} #{template(value_path(secret), secret, flag: "--from-file=", fix_file_path: fix_file_path)} | kubectl --context #{cluster_name} apply -f -"
106
+ end
107
+ end
108
+
109
+ class Label < Context
110
+ def print_install(label)
111
+ @out_io.puts "---"
112
+ @out_io.puts install_cmd(label)
113
+ end
114
+
115
+ def print_upgrade(label)
116
+ @out_io.puts "---"
117
+ @out_io.puts upgrade_cmd(label)
118
+ end
119
+
120
+ def upgrade(label)
121
+ @out_io.puts system(upgrade_cmd(label))
122
+ end
123
+
124
+ def install(label)
125
+ @out_io.puts system(install_cmd(label))
126
+ end
127
+
128
+ def upgrade_cmd(label)
129
+ "kubectl --namespace #{namespace} --context #{cluster_name} label --overwrite #{label[:resource]} #{label[:name]} #{label["value"]}"
130
+ end
131
+
132
+ def install_cmd(label)
133
+ "kubectl --namespace #{namespace} --context #{cluster_name} label --overwrite #{label[:resource]} #{label[:name]} #{label["value"]}"
134
+ end
135
+ end
136
+
137
+ class Wait < Context
138
+ def print_install(wait)
139
+ @out_io.puts "---"
140
+ @out_io.puts wait.cmd
141
+ end
142
+
143
+ def print_upgrade(wait)
144
+ @out_io.puts "---"
145
+ @out_io.puts wait.cmd
146
+ end
147
+
148
+ def upgrade(wait)
149
+ eval(wait.cmd)
150
+ end
151
+
152
+ def install(wait)
153
+ eval(wait.cmd)
154
+ end
155
+ end
156
+
157
+ class Chart < Context
158
+ class CleanBinding
159
+ def get_binding(params)
160
+ params.instance_eval do
161
+ binding
162
+ end
163
+ end
164
+ end
165
+
166
+ def build_chart(chart)
167
+ params = chart._services.map {|s| app_config.services[s.to_sym] }.map{|s| [s.name, s]}.to_h
168
+ Dir.mktmpdir do |dir|
169
+ run(templates_path: File.expand_path(chart.template, self.dir_path), params: params, output_chart_path: dir, chart: chart)
170
+ yield dir
171
+ end
172
+ end
173
+
174
+ def run(templates_path:, params:, output_chart_path:, chart: )
175
+ system("mkdir -p #{output_chart_path}")
176
+ system("mkdir -p #{File.join(output_chart_path, 'templates')}")
177
+
178
+ system("cp #{File.join(templates_path, 'values.yaml')} #{File.join(output_chart_path, 'values.yaml')}")
179
+ system("cp #{File.join(templates_path, '.helmignore')} #{File.join(output_chart_path, '.helmignore')}")
180
+ system("cp #{File.join(templates_path, 'templates/_helpers.tpl')} #{File.join(output_chart_path, 'templates/_helpers.tpl')}")
181
+
182
+ generate_chart_yaml(
183
+ templates_path: templates_path,
184
+ output_chart_path: output_chart_path,
185
+ chart_name: chart.name,
186
+ )
187
+
188
+ params.each do |app_name, subparams|
189
+ subparams[:chart] = chart
190
+ generate_documents_from_erbs(
191
+ templates_path: templates_path,
192
+ app_name: app_name,
193
+ params: subparams,
194
+ output_chart_path: output_chart_path
195
+ )
196
+ end
197
+ end
198
+
199
+ def generate_documents_from_erbs(templates_path:, app_name:, params:, output_chart_path:)
200
+ if params[:kind].nil?
201
+ warn "ERROR: Could not generate service '#{app_name}'. Missing key: 'kind'."
202
+ exit 1
203
+ end
204
+
205
+ kind = params.fetch(:kind)
206
+
207
+ Dir[File.join(templates_path, kind, '*.erb')].each do |template_path|
208
+ template_name = File.basename(template_path, '.erb')
209
+ output_path = File.join(output_chart_path, 'templates', "#{app_name}-#{template_name}")
210
+
211
+ template = Erubis::Eruby.new(File.read(template_path))
212
+ params.app_name = app_name
213
+ params.templates_path = templates_path
214
+ begin
215
+ document = template.result(CleanBinding.new.get_binding(params))
216
+ rescue Exception
217
+ puts "#{template_path} has a problem: #{$!.inspect}"
218
+ raise
219
+ end
220
+ File.write(output_path, document)
221
+ end
222
+ end
223
+
224
+ def generate_chart_yaml(templates_path:, output_chart_path:, chart_name: )
225
+ template_path = File.join(templates_path, 'Chart.yaml.erb')
226
+ output_path = File.join(output_chart_path, 'Chart.yaml')
227
+
228
+ template = Erubis::Eruby.new(File.read(template_path))
229
+ params = Hashie::Mash.new(chart_name: chart_name)
230
+ document = template.result(CleanBinding.new.get_binding(params))
231
+ File.write(output_path, document)
232
+ end
233
+
234
+ def print_install(chart)
235
+ build_chart(chart) do |chart_path|
236
+ @out_io.puts `helm template --namespace #{namespace} --kube-context #{cluster_name} #{chart.name} #{chart_path}`
237
+ end
238
+ end
239
+
240
+ def print_upgrade(chart)
241
+ print_install(chart)
242
+ end
243
+
244
+ def install(chart)
245
+ build_chart(chart) do |chart_path|
246
+ @out_io.puts system("helm install --create-namespace --namespace #{namespace} --kube-context #{cluster_name} #{chart.name} #{chart_path}")
247
+ end
248
+ end
249
+
250
+ def upgrade(chart)
251
+ build_chart(chart) do |chart_path|
252
+ @out_io.puts system("helm upgrade --namespace #{namespace} --kube-context #{cluster_name} #{chart.name} #{chart_path}")
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
258
+
259
+ class KubernetesApplication
260
+ attr_accessor :cluster_name
261
+ attr_accessor :file_path
262
+ attr_accessor :namespace
263
+ attr_accessor :app_config
264
+
265
+ def initialize(app_config: [], namespace:, cluster_name:, file_name:, out_io: STDOUT)
266
+ self.file_path = Pathname.new(file_name).parent.expand_path
267
+ self.cluster_name = cluster_name
268
+ self.namespace = namespace
269
+ self.app_config = app_config
270
+ @out_io= out_io
271
+ end
272
+
273
+ def install
274
+ each_service(:install)
275
+ end
276
+
277
+ def upgrade
278
+ each_service(:upgrade)
279
+ end
280
+
281
+ def print(method)
282
+ each_service("print_#{method}".to_sym)
283
+ end
284
+
285
+ def combine_charts(app_config)
286
+ services = app_config._service_order.map(&:to_s)
287
+ app_config._service_order.each do |name|
288
+ current_service = app_config[:services][name]
289
+ if current_service._type == "chart"
290
+ current_service._services.each do |n|
291
+ services.delete n.to_s
292
+ end
293
+ end
294
+ end
295
+ services
296
+ end
297
+
298
+ def each_service(method)
299
+ services = combine_charts(app_config)
300
+ services.each do |name|
301
+ service = app_config[:services][name]
302
+ "::Orchparty::Services::#{service._type.classify}".constantize.new(cluster_name: cluster_name, namespace: namespace, file_path: file_path, app_config: app_config, out_io: @out_io).send(method, service)
303
+ end
304
+ end
305
+ end
@@ -0,0 +1,24 @@
1
+ module Orchparty
2
+ module Plugin
3
+ @plugins = {}
4
+
5
+ def self.load_plugin(name)
6
+ begin
7
+ require "orchparty/plugins/#{name}"
8
+ raise "Plugin didn't correctly register itself" unless @plugins[name]
9
+ @plugins[name]
10
+ rescue LoadError
11
+ puts "could not load the plugin #{name}, you might install it as a gem or you need to write it by your self ;)"
12
+ false
13
+ end
14
+ end
15
+
16
+ def self.plugins
17
+ @plugins
18
+ end
19
+
20
+ def self.register_plugin(name, mod)
21
+ @plugins[name] = mod
22
+ end
23
+ end
24
+ end