orchparty 1.3.1 → 2.0.0.pre.beta
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 +5 -5
- data/lib/orchparty/ast.rb +9 -1
- data/lib/orchparty/cli.rb +34 -0
- data/lib/orchparty/dsl_parser_kubernetes.rb +304 -0
- data/lib/orchparty/kubernetes_application.rb +309 -0
- data/lib/orchparty/transformations.rb +6 -0
- data/lib/orchparty/version.rb +1 -1
- data/lib/orchparty.rb +20 -0
- data/orchparty.gemspec +2 -0
- metadata +36 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 64ca2dd610de3fdec263d50a80ba31f580868789
|
4
|
+
data.tar.gz: 75f7bc9648af4321b7e521e22826177cd2d72234
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1af9d753efabbaa79ec4125e43025049af2a44e39ee1468ba45fe23486d16719a5f4b698dc4bd411487e180c5c6189aaca275143d7d2f367845fdd101724a03a
|
7
|
+
data.tar.gz: 0f3efe9774f8aea508e4c231d2e365b3623f5e5e78ac06a4ec8f92dc8cd3cd62bac764773e4b75c51648deb48b48195b8ee35347b22d7386cc305a71d1280f42
|
data/lib/orchparty/ast.rb
CHANGED
@@ -8,6 +8,10 @@ module Orchparty
|
|
8
8
|
include Hashie::Extensions::MethodAccess
|
9
9
|
include Hashie::Extensions::Mash::KeepOriginalKeys
|
10
10
|
disable_warnings
|
11
|
+
|
12
|
+
def get_binding
|
13
|
+
binding
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
def self.hash(args = {})
|
@@ -27,7 +31,7 @@ module Orchparty
|
|
27
31
|
end
|
28
32
|
|
29
33
|
def self.application(args = {})
|
30
|
-
Node.new({services: {}, _mixins: {}, _mix:[], volumes: {}, _variables: {}, networks: {}}).merge(args)
|
34
|
+
Node.new({services: {}, _mixins: {}, _mix:[], volumes: {}, _variables: {}, networks: {}, _service_order: []}).merge(args)
|
31
35
|
end
|
32
36
|
|
33
37
|
def self.all(args = {})
|
@@ -41,5 +45,9 @@ module Orchparty
|
|
41
45
|
def self.service(args = {})
|
42
46
|
Node.new(_mix:[], _variables: {}).merge(args)
|
43
47
|
end
|
48
|
+
|
49
|
+
def self.chart(args = {})
|
50
|
+
Node.new(_mix:[], _variables: {}, _services: []).merge(args)
|
51
|
+
end
|
44
52
|
end
|
45
53
|
end
|
data/lib/orchparty/cli.rb
CHANGED
@@ -11,6 +11,40 @@ class OrchPartyApp
|
|
11
11
|
|
12
12
|
subcommand_option_handling :normal
|
13
13
|
|
14
|
+
desc "install kubernetes application"
|
15
|
+
command :print do |com|
|
16
|
+
com.flag [:cluster_name,:c,'cluster-name'], required: true, :desc => 'The cluster to install the app'
|
17
|
+
com.flag [:filename,:f,'file-name'], required: true, :desc => 'The Orchparty input file'
|
18
|
+
com.flag [:application,:a], required: true, :desc => 'The application that should be installed'
|
19
|
+
com.switch :"force-variable-definition", :default_value => false, :desc => "Raises an Error if the input contains a not defined variable"
|
20
|
+
com.flag [:method,:m], required: true, :desc => 'method to print upgrade/install'
|
21
|
+
com.action do |_, args|
|
22
|
+
Orchparty.print(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args["force-variable-definition"], file_name: args[:f], method: args[:m])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "install kubernetes application"
|
27
|
+
command :install do |com|
|
28
|
+
com.flag [:cluster_name,:c,'cluster-name'], required: true, :desc => 'The cluster to install the app'
|
29
|
+
com.flag [:filename,:f,'file-name'], required: true, :desc => 'The Orchparty input file'
|
30
|
+
com.flag [:application,:a], required: true, :desc => 'The application that should be installed'
|
31
|
+
com.switch :"force-variable-definition", :default_value => false, :desc => "Raises an Error if the input contains a not defined variable"
|
32
|
+
com.action do |_, args|
|
33
|
+
Orchparty.install(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args["force-variable-definition"], file_name: args[:f])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "upgrade kubernetes application"
|
38
|
+
command :upgrade do |com|
|
39
|
+
com.flag [:cluster_name,:c,'cluster-name'], required: true, :desc => 'The cluster to install the app'
|
40
|
+
com.flag [:filename,:f,'file-name'], required: true, :desc => 'The Orchparty input file'
|
41
|
+
com.flag [:application,:a], required: true, :desc => 'The application that should be installed'
|
42
|
+
com.switch :"force-variable-definition", :default_value => false, :desc => "Raises an Error if the input contains a not defined variable"
|
43
|
+
com.action do |_, args|
|
44
|
+
Orchparty.upgrade(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args["force-variable-definition"], file_name: args[:f])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
14
48
|
desc "Compiles a Orchparty input file to a orchestration framework configuration"
|
15
49
|
command :generate do |com|
|
16
50
|
Orchparty.plugins.each do |name, plugin|
|
@@ -0,0 +1,304 @@
|
|
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 service(name, &block)
|
72
|
+
result = ServiceMixinBuilder.build(name, block)
|
73
|
+
@mixin.services[name] = result
|
74
|
+
@mixin._mixins[name] = result
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def helm(name, &block)
|
79
|
+
result = ServiceBuilder.build(name, "helm", block)
|
80
|
+
@mixin.services[name] = result
|
81
|
+
@mixin._mixins[name] = result
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def apply(name, &block)
|
87
|
+
result = ServiceBuilder.build(name, "apply", block)
|
88
|
+
@mixin.services[name] = result
|
89
|
+
@mixin._mixins[name] = result
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
def mixin(name, &block)
|
94
|
+
@mixin._mixins[name] = ServiceMixinBuilder.build(name, block)
|
95
|
+
end
|
96
|
+
|
97
|
+
def volumes(&block)
|
98
|
+
@mixin.volumes = HashBuilder.build(block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def networks(&block)
|
102
|
+
@mixin.networks = HashBuilder.build(block)
|
103
|
+
end
|
104
|
+
|
105
|
+
def _build
|
106
|
+
@mixin
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class ApplicationBuilder < Builder
|
111
|
+
|
112
|
+
def initialize(name)
|
113
|
+
@application = AST.application(name: name)
|
114
|
+
end
|
115
|
+
|
116
|
+
def mix(name)
|
117
|
+
@application._mix << name
|
118
|
+
end
|
119
|
+
|
120
|
+
def mixin(name, &block)
|
121
|
+
@application._mixins[name] = ApplicationMixinBuilder.build(block)
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
def all(&block)
|
126
|
+
@application.all = AllBuilder.build(block)
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
def variables(&block)
|
131
|
+
@application._variables = VariableBuilder.build(block)
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
135
|
+
def volumes(&block)
|
136
|
+
@application.volumes = HashBuilder.build(block)
|
137
|
+
self
|
138
|
+
end
|
139
|
+
|
140
|
+
def helm(name, &block)
|
141
|
+
result = ServiceBuilder.build(name, "helm", block)
|
142
|
+
@application.services[name] = result
|
143
|
+
@application._service_order << name
|
144
|
+
self
|
145
|
+
end
|
146
|
+
|
147
|
+
def label(&block)
|
148
|
+
name = SecureRandom.hex
|
149
|
+
result = ServiceWithoutNameBuilder.build("label", block)
|
150
|
+
@application.services[name] = result
|
151
|
+
@application._service_order << name
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
155
|
+
def apply(name, &block)
|
156
|
+
result = ServiceBuilder.build(name, "apply", block)
|
157
|
+
@application.services[name] = result
|
158
|
+
@application._service_order << name
|
159
|
+
self
|
160
|
+
end
|
161
|
+
|
162
|
+
def secret_generic(name, &block)
|
163
|
+
result = ServiceBuilder.build(name, "secret_generic", block)
|
164
|
+
@application.services[name] = result
|
165
|
+
@application._service_order << name
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
def wait(&block)
|
170
|
+
name = SecureRandom.hex
|
171
|
+
result = ServiceBuilder.build(name, "wait", block)
|
172
|
+
@application.services[name] = result
|
173
|
+
@application._service_order << name
|
174
|
+
self
|
175
|
+
end
|
176
|
+
|
177
|
+
def chart(name, &block)
|
178
|
+
@application.services[name] = ChartBuilder.build(name, @application, "chart", block)
|
179
|
+
@application._service_order << name
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
183
|
+
def _build
|
184
|
+
@application
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class HashBuilder < Builder
|
189
|
+
|
190
|
+
def method_missing(_, *values, &block)
|
191
|
+
if block_given?
|
192
|
+
value = HashBuilder.build(block)
|
193
|
+
if values.count == 1
|
194
|
+
@hash ||= AST.hash
|
195
|
+
@hash[values.first.to_sym] = value
|
196
|
+
else
|
197
|
+
@hash ||= AST.array
|
198
|
+
@hash << value
|
199
|
+
end
|
200
|
+
else
|
201
|
+
value = values.first
|
202
|
+
if value.is_a? Hash
|
203
|
+
@hash ||= AST.hash
|
204
|
+
key, value = value.first
|
205
|
+
@hash[key.to_sym] = value
|
206
|
+
else
|
207
|
+
@hash ||= AST.array
|
208
|
+
@hash << value
|
209
|
+
end
|
210
|
+
end
|
211
|
+
self
|
212
|
+
end
|
213
|
+
|
214
|
+
def _build
|
215
|
+
@hash
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class VariableBuilder < HashBuilder
|
220
|
+
def _build
|
221
|
+
super || {}
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
class CommonBuilder < Builder
|
226
|
+
|
227
|
+
def initialize(node)
|
228
|
+
@node = node
|
229
|
+
end
|
230
|
+
|
231
|
+
def mix(name)
|
232
|
+
@node._mix << name
|
233
|
+
end
|
234
|
+
|
235
|
+
def method_missing(name, *values, &block)
|
236
|
+
if block_given?
|
237
|
+
assign_or_merge(@node, name, HashBuilder.build(block))
|
238
|
+
else
|
239
|
+
assign_or_merge(@node, name, values.first)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def _build
|
244
|
+
@node
|
245
|
+
end
|
246
|
+
|
247
|
+
def variables(&block)
|
248
|
+
@node._variables ||= {}
|
249
|
+
@node._variables = @node._variables.merge(VariableBuilder.build(block))
|
250
|
+
self
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class AllBuilder < CommonBuilder
|
255
|
+
def initialize
|
256
|
+
super AST.all
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class ApplicationMixinBuilder < CommonBuilder
|
261
|
+
def initialize
|
262
|
+
super AST.application_mixin
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class ServiceWithoutNameBuilder < CommonBuilder
|
267
|
+
|
268
|
+
def initialize( type)
|
269
|
+
super AST.service(_type: type)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
class ServiceBuilder < CommonBuilder
|
274
|
+
|
275
|
+
def initialize(name, type)
|
276
|
+
super AST.service(name: name, _type: type)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
class ServiceMixinBuilder < CommonBuilder
|
281
|
+
|
282
|
+
def initialize(name)
|
283
|
+
super AST.service(name: name)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
class ChartBuilder < CommonBuilder
|
288
|
+
def initialize(name, application, type)
|
289
|
+
super AST.chart(name: name, _type: type )
|
290
|
+
@application = application
|
291
|
+
end
|
292
|
+
|
293
|
+
def service(name, &block)
|
294
|
+
result = ServiceBuilder.build(name, "chart-service", block)
|
295
|
+
|
296
|
+
name = "chart-#{@node.name}-#{name}"
|
297
|
+
@application.services[name] = result
|
298
|
+
@application._service_order << name
|
299
|
+
@node._services << name
|
300
|
+
self
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
@@ -0,0 +1,309 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'erubis'
|
3
|
+
require 'open3'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'byebug'
|
6
|
+
require 'yaml'
|
7
|
+
require 'tempfile'
|
8
|
+
require 'active_support'
|
9
|
+
require 'active_support/core_ext'
|
10
|
+
|
11
|
+
|
12
|
+
module Orchparty
|
13
|
+
module Services
|
14
|
+
|
15
|
+
class Context
|
16
|
+
attr_accessor :cluster_name
|
17
|
+
attr_accessor :namespace
|
18
|
+
attr_accessor :dir_path
|
19
|
+
attr_accessor :app_config
|
20
|
+
|
21
|
+
def initialize(cluster_name: , namespace:, file_path: , app_config:)
|
22
|
+
self.cluster_name = cluster_name
|
23
|
+
self.namespace = namespace
|
24
|
+
self.dir_path = file_path
|
25
|
+
self.app_config = app_config
|
26
|
+
end
|
27
|
+
|
28
|
+
def template(file_path, helm, flag: "-f ", fix_file_path: nil)
|
29
|
+
return "" unless file_path
|
30
|
+
file_path = File.join(self.dir_path, file_path)
|
31
|
+
if(file_path.end_with?(".erb"))
|
32
|
+
helm.application = OpenStruct.new(cluster_name: cluster_name, namespace: namespace)
|
33
|
+
template = ERB.new File.read(file_path )
|
34
|
+
yaml = template.result(helm.get_binding)
|
35
|
+
file = Tempfile.new("kube-deploy.yaml")
|
36
|
+
file.write(yaml)
|
37
|
+
file.close
|
38
|
+
file_path = file.path
|
39
|
+
end
|
40
|
+
"#{flag}#{fix_file_path || file_path}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def print_install(helm)
|
44
|
+
puts "---"
|
45
|
+
puts install_cmd(helm, value_path(helm))
|
46
|
+
puts "---"
|
47
|
+
puts File.read(template(value_path(helm), helm, flag: "")) if value_path(helm)
|
48
|
+
end
|
49
|
+
|
50
|
+
def print_upgrade(helm)
|
51
|
+
puts "---"
|
52
|
+
puts install_cmd(helm, value_path(helm))
|
53
|
+
puts "---"
|
54
|
+
puts File.read(template(value_path(helm), helm, flag: "")) if value_path(helm)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def upgrade(helm)
|
59
|
+
puts system(upgrade_cmd(helm))
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def install(helm)
|
64
|
+
puts system(install_cmd(helm))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Helm < Context
|
69
|
+
|
70
|
+
def value_path(helm)
|
71
|
+
helm[:values]
|
72
|
+
end
|
73
|
+
|
74
|
+
def upgrade_cmd(helm, fix_file_path = nil)
|
75
|
+
"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)}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def install_cmd(helm, fix_file_path = nil)
|
79
|
+
"helm install --namespace #{namespace} --kube-context #{cluster_name} --version #{helm.version} --name #{helm.name} #{helm.chart} #{template(value_path(helm), helm, fix_file_path: fix_file_path)}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Apply < Context
|
84
|
+
|
85
|
+
def value_path(apply)
|
86
|
+
apply[:name]
|
87
|
+
end
|
88
|
+
|
89
|
+
def upgrade_cmd(apply, fix_file_path = nil)
|
90
|
+
"kubectl apply --namespace #{namespace} --context #{cluster_name} #{template(value_path(apply), apply, fix_file_path: fix_file_path)}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def install_cmd(apply, fix_file_path = nil)
|
94
|
+
"kubectl apply --namespace #{namespace} --context #{cluster_name} #{template(value_path(apply), apply, fix_file_path: fix_file_path)}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class SecretGeneric < Context
|
99
|
+
|
100
|
+
def value_path(secret)
|
101
|
+
secret[:from_file]
|
102
|
+
end
|
103
|
+
|
104
|
+
def upgrade_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 apply -f -"
|
106
|
+
end
|
107
|
+
|
108
|
+
def install_cmd(secret, fix_file_path=nil)
|
109
|
+
"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 apply -f -"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class Label < Context
|
114
|
+
|
115
|
+
def print_install(label)
|
116
|
+
puts "---"
|
117
|
+
puts install_cmd(label)
|
118
|
+
end
|
119
|
+
|
120
|
+
def print_upgrade(label)
|
121
|
+
puts "---"
|
122
|
+
puts upgrade_cmd(label)
|
123
|
+
end
|
124
|
+
|
125
|
+
def upgrade(label)
|
126
|
+
puts system(upgrade_cmd(label))
|
127
|
+
end
|
128
|
+
|
129
|
+
def install(label)
|
130
|
+
puts system(install_cmd(label))
|
131
|
+
end
|
132
|
+
|
133
|
+
def upgrade_cmd(label)
|
134
|
+
"kubectl --namespace #{namespace} --context #{cluster_name} label --overwrite #{label[:resource]} #{label[:name]} #{label["value"]}"
|
135
|
+
end
|
136
|
+
|
137
|
+
def install_cmd(label)
|
138
|
+
"kubectl --namespace #{namespace} --context #{cluster_name} label --overwrite #{label[:resource]} #{label[:name]} #{label["value"]}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class Wait < Context
|
143
|
+
|
144
|
+
def print_install(wait)
|
145
|
+
puts "---"
|
146
|
+
puts wait.cmd
|
147
|
+
end
|
148
|
+
|
149
|
+
def print_upgrade(wait)
|
150
|
+
puts "---"
|
151
|
+
puts wait.cmd
|
152
|
+
end
|
153
|
+
|
154
|
+
def upgrade(wait)
|
155
|
+
eval(wait.cmd)
|
156
|
+
end
|
157
|
+
|
158
|
+
def install(wait)
|
159
|
+
eval(wait.cmd)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class Chart < Context
|
164
|
+
|
165
|
+
class CleanBinding
|
166
|
+
def get_binding(params)
|
167
|
+
params.instance_eval do
|
168
|
+
binding
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def build_chart(chart)
|
174
|
+
params = chart._services.map {|s| app_config.services[s.to_sym] }.map{|s| [s.name, s]}.to_h
|
175
|
+
Dir.mktmpdir do |dir|
|
176
|
+
run(templates_path: File.join(self.dir_path, chart.template), params: params, output_chart_path: dir, chart: chart)
|
177
|
+
yield dir
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
def run(templates_path:, params:, output_chart_path:, chart: )
|
183
|
+
|
184
|
+
system("mkdir -p #{output_chart_path}")
|
185
|
+
system("mkdir -p #{File.join(output_chart_path, 'templates')}")
|
186
|
+
|
187
|
+
system("cp #{File.join(templates_path, 'values.yaml')} #{File.join(output_chart_path, 'values.yaml')}")
|
188
|
+
system("cp #{File.join(templates_path, '.helmignore')} #{File.join(output_chart_path, '.helmignore')}")
|
189
|
+
system("cp #{File.join(templates_path, 'templates/_helpers.tpl')} #{File.join(output_chart_path, 'templates/_helpers.tpl')}")
|
190
|
+
|
191
|
+
generate_chart_yaml(
|
192
|
+
templates_path: templates_path,
|
193
|
+
output_chart_path: output_chart_path,
|
194
|
+
chart_name: chart.name,
|
195
|
+
)
|
196
|
+
|
197
|
+
params.each do |app_name, subparams|
|
198
|
+
subparams[:chart] = chart
|
199
|
+
generate_documents_from_erbs(
|
200
|
+
templates_path: templates_path,
|
201
|
+
app_name: app_name,
|
202
|
+
params: subparams,
|
203
|
+
output_chart_path: output_chart_path
|
204
|
+
)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def generate_documents_from_erbs(templates_path:, app_name:, params:, output_chart_path:)
|
209
|
+
kind = params.fetch(:kind)
|
210
|
+
|
211
|
+
Dir[File.join(templates_path, kind, '*.erb')].each do |template_path|
|
212
|
+
template_name = File.basename(template_path, '.erb')
|
213
|
+
output_path = File.join(output_chart_path, 'templates', "#{app_name}-#{template_name}")
|
214
|
+
|
215
|
+
template = Erubis::Eruby.new(File.read(template_path))
|
216
|
+
params.app_name = app_name
|
217
|
+
document = template.result(CleanBinding.new.get_binding(params))
|
218
|
+
File.write(output_path, document)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def generate_chart_yaml(templates_path:, output_chart_path:, chart_name: )
|
223
|
+
template_path = File.join(templates_path, 'Chart.yaml.erb')
|
224
|
+
output_path = File.join(output_chart_path, 'Chart.yaml')
|
225
|
+
|
226
|
+
template = Erubis::Eruby.new(File.read(template_path))
|
227
|
+
params = Hashie::Mash.new(chart_name: chart_name)
|
228
|
+
document = template.result(CleanBinding.new.get_binding(params))
|
229
|
+
File.write(output_path, document)
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
|
234
|
+
def print_install(chart)
|
235
|
+
build_chart(chart) do |chart_path|
|
236
|
+
puts `helm template --namespace #{namespace} --kube-context #{cluster_name} --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
|
+
puts system("helm install --namespace #{namespace} --kube-context #{cluster_name} --name #{chart.name} #{chart_path}")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def upgrade(chart)
|
251
|
+
build_chart(chart) do |chart_path|
|
252
|
+
puts system("helm upgrade --namespace #{namespace} --kube-context #{cluster_name} #{chart.name} #{chart_path}")
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
class KubernetesApplication
|
263
|
+
attr_accessor :cluster_name
|
264
|
+
attr_accessor :file_path
|
265
|
+
attr_accessor :namespace
|
266
|
+
attr_accessor :app_config
|
267
|
+
|
268
|
+
def initialize(app_config: [], namespace:, cluster_name:, file_name:)
|
269
|
+
self.file_path = Pathname.new(file_name).parent.expand_path
|
270
|
+
self.cluster_name = cluster_name
|
271
|
+
self.namespace = namespace
|
272
|
+
self.app_config = app_config
|
273
|
+
end
|
274
|
+
|
275
|
+
def install
|
276
|
+
each_service(:install)
|
277
|
+
end
|
278
|
+
|
279
|
+
def upgrade
|
280
|
+
each_service(:upgrade)
|
281
|
+
end
|
282
|
+
|
283
|
+
def print(method)
|
284
|
+
each_service("print_#{method}".to_sym)
|
285
|
+
end
|
286
|
+
|
287
|
+
def combine_charts(app_config)
|
288
|
+
services = app_config._service_order.map(&:to_s)
|
289
|
+
app_config._service_order.each do |name|
|
290
|
+
current_service = app_config[:services][name]
|
291
|
+
if current_service._type == "chart"
|
292
|
+
current_service._services.each do |n|
|
293
|
+
services.delete n.to_s
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
services
|
298
|
+
end
|
299
|
+
|
300
|
+
def each_service(method)
|
301
|
+
services = combine_charts(app_config)
|
302
|
+
services.each do |name|
|
303
|
+
service = app_config[:services][name]
|
304
|
+
"::Orchparty::Services::#{service._type.classify}".constantize.new(cluster_name: cluster_name, namespace: namespace, file_path: file_path, app_config: app_config).send(method, service)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
|
@@ -14,5 +14,11 @@ module Orchparty
|
|
14
14
|
ast = RemoveInternal.new.transform(ast)
|
15
15
|
ast = Sort.new.transform(ast)
|
16
16
|
end
|
17
|
+
|
18
|
+
def self.transform_kubernetes(ast, opts = {})
|
19
|
+
ast = All.new.transform(ast)
|
20
|
+
ast = Mixin.new.transform(ast)
|
21
|
+
ast = Variable.new(opts).transform(ast)
|
22
|
+
end
|
17
23
|
end
|
18
24
|
end
|
data/lib/orchparty/version.rb
CHANGED
data/lib/orchparty.rb
CHANGED
@@ -4,7 +4,9 @@ require "orchparty/ast"
|
|
4
4
|
require "orchparty/context"
|
5
5
|
require "orchparty/transformations"
|
6
6
|
require "orchparty/dsl_parser"
|
7
|
+
require "orchparty/dsl_parser_kubernetes"
|
7
8
|
require "orchparty/plugin"
|
9
|
+
require "orchparty/kubernetes_application"
|
8
10
|
require "hash"
|
9
11
|
|
10
12
|
module Orchparty
|
@@ -30,4 +32,22 @@ module Orchparty
|
|
30
32
|
def self.generate(plugin_name, options, plugin_options)
|
31
33
|
plugins[plugin_name].generate(ast(options), plugin_options)
|
32
34
|
end
|
35
|
+
|
36
|
+
def self.install(cluster_name: , application_name: , force_variable_definition:, file_name: )
|
37
|
+
app_config = Transformations.transform_kubernetes(Orchparty::Kubernetes::DSLParser.new(file_name).parse, force_variable_definition: force_variable_definition).applications[application_name]
|
38
|
+
app = KubernetesApplication.new(app_config: app_config, namespace: application_name, cluster_name: cluster_name, file_name: file_name)
|
39
|
+
app.install
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.upgrade(cluster_name: , application_name: , force_variable_definition:, file_name: )
|
43
|
+
app_config = Transformations.transform_kubernetes(Orchparty::Kubernetes::DSLParser.new(file_name).parse, force_variable_definition: force_variable_definition).applications[application_name]
|
44
|
+
app = KubernetesApplication.new(app_config: app_config, namespace: application_name, cluster_name: cluster_name, file_name: file_name)
|
45
|
+
app.upgrade
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.print(cluster_name: , application_name: , force_variable_definition:, file_name:, method: )
|
49
|
+
app_config = Transformations.transform_kubernetes(Orchparty::Kubernetes::DSLParser.new(file_name).parse, force_variable_definition: force_variable_definition).applications[application_name]
|
50
|
+
app = KubernetesApplication.new(app_config: app_config, namespace: application_name, cluster_name: cluster_name, file_name: file_name)
|
51
|
+
app.print(method)
|
52
|
+
end
|
33
53
|
end
|
data/orchparty.gemspec
CHANGED
@@ -26,6 +26,8 @@ Gem::Specification.new do |spec|
|
|
26
26
|
|
27
27
|
spec.add_dependency "hashie", "~> 3.5.6"
|
28
28
|
spec.add_dependency "gli", "~> 2.16.0"
|
29
|
+
spec.add_dependency "activesupport"
|
30
|
+
spec.add_dependency "erubis"
|
29
31
|
spec.add_development_dependency "bundler", "~> 2.0.1"
|
30
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
31
33
|
spec.add_development_dependency "rspec", "~> 3.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orchparty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.pre.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jannis Huebl
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -38,6 +38,34 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 2.16.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: erubis
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: bundler
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,6 +140,8 @@ files:
|
|
112
140
|
- lib/orchparty/cli.rb
|
113
141
|
- lib/orchparty/context.rb
|
114
142
|
- lib/orchparty/dsl_parser.rb
|
143
|
+
- lib/orchparty/dsl_parser_kubernetes.rb
|
144
|
+
- lib/orchparty/kubernetes_application.rb
|
115
145
|
- lib/orchparty/plugin.rb
|
116
146
|
- lib/orchparty/plugins/docker_compose_v1.rb
|
117
147
|
- lib/orchparty/plugins/docker_compose_v2.rb
|
@@ -138,11 +168,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
168
|
version: '0'
|
139
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
170
|
requirements:
|
141
|
-
- - "
|
171
|
+
- - ">"
|
142
172
|
- !ruby/object:Gem::Version
|
143
|
-
version:
|
173
|
+
version: 1.3.1
|
144
174
|
requirements: []
|
145
|
-
|
175
|
+
rubyforge_project:
|
176
|
+
rubygems_version: 2.6.14.4
|
146
177
|
signing_key:
|
147
178
|
specification_version: 4
|
148
179
|
summary: Write your orchestration configuration with a Ruby DSL that allows you to
|