cl-magic 0.4.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +16 -2
- data/cl-magic.gemspec +5 -0
- data/lib/cl/magic/cl +21 -14
- data/lib/cl/magic/cl-ai-chat +117 -0
- data/lib/cl/magic/cl-ai-query +116 -0
- data/lib/cl/magic/cl-ai-store-jira +158 -0
- data/lib/cl/magic/cl-dk +23 -456
- data/lib/cl/magic/cl-dk-make +174 -0
- data/lib/cl/magic/cl-dk-make-world +163 -0
- data/lib/cl/magic/cl-dk-parts +253 -0
- data/lib/cl/magic/cl-dk-world +140 -0
- data/lib/cl/magic/cl-jira-fetch +15 -47
- data/lib/cl/magic/cl-jira-fetch-by-epics +112 -0
- data/lib/cl/magic/cl-jira-to-elastic +126 -0
- data/lib/cl/magic/cl-jira-to-markdown +68 -0
- data/lib/cl/magic/{cl-jira-stats → cl-jira-to-stats} +13 -10
- data/lib/cl/magic/cl-kube-logs +3 -1
- data/lib/cl/magic/common/ai_prompt.rb +169 -0
- data/lib/cl/magic/common/ai_text_splitter.rb +78 -0
- data/lib/cl/magic/common/common_options.rb +1 -1
- data/lib/cl/magic/common/elastic.rb +41 -0
- data/lib/cl/magic/common/jira.rb +169 -42
- data/lib/cl/magic/common/milvus.rb +78 -0
- data/lib/cl/magic/dk/help_printer.rb +29 -0
- data/lib/cl/magic/dk/parts_merger.rb +67 -0
- data/lib/cl/magic/dk/world_settings.rb +52 -0
- data/lib/cl/magic/dk/yaml_arg_munger.rb +107 -0
- data/lib/cl/magic/version.rb +1 -1
- metadata +77 -3
data/lib/cl/magic/cl-dk
CHANGED
@@ -10,101 +10,18 @@ require 'cl/magic/common/common_options.rb'
|
|
10
10
|
require 'cl/magic/common/logging.rb'
|
11
11
|
require 'cl/magic/common/parse_and_pick.rb'
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
#
|
18
|
-
|
19
|
-
def get_base_compose_hash()
|
20
|
-
cmd = "cd #{@working_dir} && docker compose config 2> /dev/null"
|
21
|
-
return YAML.load(`#{cmd}`)
|
22
|
-
end
|
23
|
-
|
24
|
-
def get_save_parts_filepath()
|
25
|
-
return File.join(@working_dir, ".cl-dk-parts.yml")
|
26
|
-
end
|
13
|
+
require_relative 'dk/help_printer'
|
14
|
+
require_relative 'dk/yaml_arg_munger'
|
15
|
+
require_relative 'dk/world_settings'
|
16
|
+
require_relative 'dk/parts_merger'
|
27
17
|
|
28
|
-
|
29
|
-
compose_hash = get_base_compose_hash()
|
30
|
-
dk_parts_hash = {}
|
31
|
-
dk_make_hash = {}
|
32
|
-
if compose_hash
|
33
|
-
compose_hash = merge_world_files(compose_hash, show_help=ARGV.include?("--help"))
|
34
|
-
dk_parts_hash = compose_hash['x-dk-parts'] ? compose_hash.delete('x-dk-parts') : {}
|
35
|
-
dk_make_hash = compose_hash['x-dk-make'] ? compose_hash.delete('x-dk-make') : {}
|
36
|
-
end
|
37
|
-
return compose_hash, dk_parts_hash, dk_make_hash
|
38
|
-
end
|
39
|
-
|
40
|
-
# world
|
41
|
-
|
42
|
-
def get_repo_basename()
|
43
|
-
command = "cd #{@working_dir} && basename $(git remote get-url origin 2> /dev/null) .git"
|
44
|
-
repo_basename = TTY::Command.new(:printer => :null).run(command).out.gsub('.git', '').strip.chomp
|
45
|
-
if repo_basename==".git" or repo_basename==""
|
46
|
-
return File.basename(@working_dir)
|
47
|
-
end
|
48
|
-
return repo_basename
|
49
|
-
end
|
50
|
-
|
51
|
-
def get_world_settings_filepath()
|
52
|
-
return File.join(".cl-dk-world.yml")
|
53
|
-
end
|
54
|
-
|
55
|
-
def get_world_settings_hash()
|
56
|
-
filepath = get_world_settings_filepath()
|
57
|
-
return File.exist?(filepath) ? YAML.load_file(filepath) : {}
|
58
|
-
end
|
59
|
-
|
60
|
-
def get_world_path_from_settings()
|
61
|
-
world_settings = get_world_settings_hash()
|
62
|
-
if world_settings.key?(:world_path) and world_settings.key?(:context)
|
63
|
-
return File.join(world_settings[:world_path], world_settings[:context])
|
64
|
-
end
|
65
|
-
return ""
|
66
|
-
end
|
67
|
-
|
68
|
-
def save_world_settings(world_settings_hash)
|
69
|
-
filepath = get_world_settings_filepath()
|
70
|
-
tempfile = File.new(filepath, 'w')
|
71
|
-
tempfile.write(world_settings_hash.to_yaml)
|
72
|
-
tempfile.close
|
73
|
-
end
|
74
|
-
|
75
|
-
def get_world_project_path()
|
76
|
-
repo_basename = get_repo_basename()
|
77
|
-
world_path = get_world_path_from_settings()
|
78
|
-
return File.join(world_path, repo_basename) if world_path and repo_basename
|
79
|
-
return nil
|
80
|
-
end
|
18
|
+
@logger = get_logger()
|
81
19
|
|
82
20
|
#
|
83
21
|
# Help Methods
|
84
22
|
#
|
85
23
|
|
86
|
-
def
|
87
|
-
if $stdout.isatty
|
88
|
-
if help.nil?
|
89
|
-
@logger.puts("#{key.ljust(15, ' ')} ???no help???")
|
90
|
-
else
|
91
|
-
key = key.ljust(15, ' ')
|
92
|
-
help_parts = help.split(";")
|
93
|
-
|
94
|
-
# first line
|
95
|
-
@logger.puts(key, help_parts.shift)
|
96
|
-
|
97
|
-
# following lines
|
98
|
-
padding = "".ljust(15, ' ')
|
99
|
-
help_parts.each do |p|
|
100
|
-
@logger.puts(padding, p)
|
101
|
-
end
|
102
|
-
@logger.puts("") if help.end_with?(";")
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def print_dk_help(dk_parts_hash, dk_make_hash, args)
|
24
|
+
def try_print_dk_help(dk_parts_hash, dk_make_hash, args)
|
108
25
|
no_args = args.empty?()
|
109
26
|
asked_for_help = args.include?('--help')
|
110
27
|
has_dk_commands = dk_parts_hash.keys.any?
|
@@ -115,15 +32,9 @@ def print_dk_help(dk_parts_hash, dk_make_hash, args)
|
|
115
32
|
puts ""
|
116
33
|
puts "Run docker compose while munging yamls in sophisticated ways."
|
117
34
|
puts ""
|
118
|
-
if get_repo_basename
|
119
|
-
puts "PROJ INFO"
|
120
|
-
puts " - Repo basename: #{get_repo_basename}"
|
121
|
-
puts " - World filepath: #{get_world_project_path()}"
|
122
|
-
puts ""
|
123
|
-
end
|
124
35
|
puts "PROJ PARTS"
|
125
36
|
dk_parts_hash.keys.each do |key|
|
126
|
-
print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
37
|
+
@help_printer.print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
127
38
|
end
|
128
39
|
puts ""
|
129
40
|
puts "YML TOKENS"
|
@@ -133,208 +44,10 @@ def print_dk_help(dk_parts_hash, dk_make_hash, args)
|
|
133
44
|
puts " - <dk-project-path> absolute filepath to world/project directory"
|
134
45
|
puts " - <dk-working-path> absolute filepath to location dk command was run from"
|
135
46
|
puts ""
|
136
|
-
puts "ADDITIONAL TURNKEY COMMANDS"
|
137
|
-
puts " - dk set-world sets the location of the world directory"
|
138
|
-
puts " - dk make turnkey commands for a project"
|
139
|
-
puts " - dk set-parts save parts so they are automatically applied to commands"
|
140
|
-
puts ""
|
141
47
|
puts "-------------------------"
|
142
48
|
end
|
143
49
|
end
|
144
50
|
|
145
|
-
def print_make_help(dk_parts_hash, dk_make_hash)
|
146
|
-
if $stdout.isatty
|
147
|
-
puts ""
|
148
|
-
puts "Usage: dk [DK_PARTS] make COMMAND"
|
149
|
-
puts ""
|
150
|
-
puts "Make commands designed to make your developer experience more turnkey"
|
151
|
-
puts ""
|
152
|
-
puts "Parts:"
|
153
|
-
dk_parts_hash.keys.each do |key|
|
154
|
-
print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
155
|
-
end
|
156
|
-
puts ""
|
157
|
-
puts "Commands:"
|
158
|
-
dk_make_hash.keys.each do |key|
|
159
|
-
print_dk_help_line(key, dk_make_hash[key].fetch('help'))
|
160
|
-
end
|
161
|
-
puts ""
|
162
|
-
else
|
163
|
-
dk_make_hash.keys.each do |key|
|
164
|
-
puts key
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
def print_set_world_help()
|
170
|
-
puts ""
|
171
|
-
puts "Usage: dk set-world PATH"
|
172
|
-
puts ""
|
173
|
-
puts "Set the folder that contains dk-world configuration"
|
174
|
-
puts ""
|
175
|
-
end
|
176
|
-
|
177
|
-
def print_set_parts_help()
|
178
|
-
compose_hash, dk_parts_hash, dk_make_hash = get_base_compose_parts_and_make_hashes()
|
179
|
-
|
180
|
-
# print help
|
181
|
-
puts ""
|
182
|
-
puts "Usage: dk [DK_PARTS] set-parts"
|
183
|
-
puts ""
|
184
|
-
puts "Set parts for a project and apply to every 'dk' command"
|
185
|
-
puts ""
|
186
|
-
if dk_parts_hash.keys.any?
|
187
|
-
puts "Parts:"
|
188
|
-
dk_parts_hash.keys.each do |key|
|
189
|
-
print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
190
|
-
end
|
191
|
-
puts ""
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
#
|
196
|
-
# Yaml Merging
|
197
|
-
#
|
198
|
-
|
199
|
-
class ::Hash
|
200
|
-
def dk_merge(second)
|
201
|
-
merger = proc { |_, v1, v2|
|
202
|
-
if Hash === v1 && Hash === v2
|
203
|
-
v1.merge(v2, &merger)
|
204
|
-
else
|
205
|
-
if Array === v1 && Array === v2
|
206
|
-
if v2.first=="<dk-replace>"
|
207
|
-
v2[1..-1] # everything but the first item
|
208
|
-
else
|
209
|
-
v1 | v2 # union arrays
|
210
|
-
end
|
211
|
-
else
|
212
|
-
if [:undefined, nil, :nil].include?(v2)
|
213
|
-
v1
|
214
|
-
else
|
215
|
-
v2
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
}
|
220
|
-
merge(second.to_h, &merger)
|
221
|
-
end
|
222
|
-
def dk_reject!(&blk)
|
223
|
-
self.each do |k, v|
|
224
|
-
v.dk_reject!(&blk) if v.is_a?(Hash)
|
225
|
-
self.delete(k) if blk.call(k, v)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def dk_merge_and_remove(compose_hash, yml_hash)
|
231
|
-
# remove help & merge
|
232
|
-
clean_yml = yml_hash.clone
|
233
|
-
clean_yml.delete('help')
|
234
|
-
return compose_hash.dk_merge(clean_yml).dk_reject! { |k, v| v=='<dk-remove>' }
|
235
|
-
end
|
236
|
-
|
237
|
-
def merge_world_files(compose_hash, show_help=false)
|
238
|
-
dk_proj_path = get_world_project_path()
|
239
|
-
if dk_proj_path
|
240
|
-
print_dk_help_line("dk-project-path", "#{dk_proj_path}") if show_help and $stdout.isatty
|
241
|
-
|
242
|
-
Dir.glob("#{dk_proj_path}/*.yml").sort.each do |filepath|
|
243
|
-
print_dk_help_line("dk-world", "#{filepath}") if show_help and $stdout.isatty
|
244
|
-
|
245
|
-
# read file and replace
|
246
|
-
contents = File.read(filepath)
|
247
|
-
contents.gsub!('<dk-world-path>', get_world_path_from_settings())
|
248
|
-
contents.gsub!('<dk-project-path>', dk_proj_path)
|
249
|
-
contents.gsub!('<dk-working-path>', @working_dir)
|
250
|
-
|
251
|
-
# yml merge
|
252
|
-
yml_hash = YAML.load(contents)
|
253
|
-
compose_hash = dk_merge_and_remove(compose_hash, yml_hash)
|
254
|
-
end
|
255
|
-
end
|
256
|
-
return compose_hash
|
257
|
-
end
|
258
|
-
|
259
|
-
def get_saved_parts(dk_parts_hash)
|
260
|
-
saved_part_keys = []
|
261
|
-
filepath = get_save_parts_filepath()
|
262
|
-
|
263
|
-
# merge
|
264
|
-
if File.exist?(filepath)
|
265
|
-
saved_parts = YAML.load_file(filepath)
|
266
|
-
saved_parts.each do |potential_part_key|
|
267
|
-
dk_part = dk_parts_hash.fetch(potential_part_key, nil) # yml detail
|
268
|
-
if dk_part
|
269
|
-
saved_part_keys << potential_part_key
|
270
|
-
else
|
271
|
-
@logger.error "invalid saved part: #{potential_part_key}"
|
272
|
-
exit 1
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
return saved_part_keys
|
277
|
-
end
|
278
|
-
|
279
|
-
def merge_parts_save_and_prep_args(compose_hash, dk_parts_hash, dk_make_hash, saved_part_keys)
|
280
|
-
tempfile = File.new(File.join(@working_dir, ".cl-dk.yml"), 'w')
|
281
|
-
args = ARGV.clone
|
282
|
-
|
283
|
-
# dk help
|
284
|
-
print_dk_help(dk_parts_hash, dk_make_hash, args)
|
285
|
-
|
286
|
-
def print_and_merge_part(part_key, dk_part, compose_hash)
|
287
|
-
|
288
|
-
# print
|
289
|
-
if $stdout.isatty
|
290
|
-
help_str = dk_part.fetch('help')
|
291
|
-
print_dk_help_line("#{part_key}", "#{help_str ? '- ' + help_str : ''}") if dk_part.keys.any?
|
292
|
-
end
|
293
|
-
# merge
|
294
|
-
return dk_merge_and_remove(compose_hash, dk_part)
|
295
|
-
end
|
296
|
-
|
297
|
-
# saved parts
|
298
|
-
saved_part_keys.each do |potential_part_key|
|
299
|
-
dk_part = dk_parts_hash.fetch(potential_part_key, nil) # yml detail
|
300
|
-
compose_hash = print_and_merge_part(potential_part_key, dk_part, compose_hash) if dk_part
|
301
|
-
end
|
302
|
-
|
303
|
-
# arg parts
|
304
|
-
selected_part_keys = []
|
305
|
-
while true
|
306
|
-
potential_part_key = args.first
|
307
|
-
dk_part = dk_parts_hash.fetch(potential_part_key, nil) # yml detail
|
308
|
-
if dk_part
|
309
|
-
|
310
|
-
# unless already applied
|
311
|
-
unless saved_part_keys.include?(potential_part_key)
|
312
|
-
compose_hash = print_and_merge_part(potential_part_key, dk_part, compose_hash)
|
313
|
-
end
|
314
|
-
selected_part_keys << potential_part_key
|
315
|
-
args.shift # remove part arg
|
316
|
-
else
|
317
|
-
break
|
318
|
-
end
|
319
|
-
end
|
320
|
-
@logger.puts "" if $stdout.isatty # tailing line break
|
321
|
-
tempfile.write(compose_hash.to_yaml) # write it to the tempfile
|
322
|
-
|
323
|
-
# clone args
|
324
|
-
args = args.clone
|
325
|
-
|
326
|
-
# remove existing '-f' flag, if needed
|
327
|
-
file_flag_index = args.index('-f')
|
328
|
-
if file_flag_index==0
|
329
|
-
args.delete_at(file_flag_index)
|
330
|
-
args.delete_at(file_flag_index)
|
331
|
-
end
|
332
|
-
args.unshift('-f', tempfile.path) # add new '-f' flag
|
333
|
-
|
334
|
-
tempfile.close
|
335
|
-
return args, selected_part_keys
|
336
|
-
end
|
337
|
-
|
338
51
|
#
|
339
52
|
# Run: DK
|
340
53
|
#
|
@@ -345,147 +58,29 @@ def run_dk(compose_args)
|
|
345
58
|
end
|
346
59
|
|
347
60
|
#
|
348
|
-
#
|
61
|
+
# Features
|
349
62
|
#
|
350
63
|
|
351
|
-
def
|
352
|
-
world_settings = get_world_settings_hash()
|
64
|
+
def do_work()
|
353
65
|
|
354
|
-
#
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
else
|
360
|
-
if world_path.start_with?("/") or world_path.start_with?("~")
|
361
|
-
world_path = File.expand_path(world_path)
|
362
|
-
else
|
363
|
-
world_path = File.expand_path(File.join(@working_dir, world_path))
|
364
|
-
end
|
365
|
-
end
|
66
|
+
# utils
|
67
|
+
@help_printer = HelpPrinter.new(@logger)
|
68
|
+
@world_settings = WorldSettings.new(@working_dir)
|
69
|
+
@yaml_arg_munger = YamlArgMunger.new(@working_dir, @world_settings)
|
70
|
+
@parts_merger = PartsMerger.new(@working_dir, @yaml_arg_munger, @help_printer, @logger)
|
366
71
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
72
|
+
# world files
|
73
|
+
compose_hash, dk_parts_hash, dk_make_hash = @yaml_arg_munger.get_base_compose_parts_and_make_hashes()
|
74
|
+
if compose_hash
|
75
|
+
try_print_dk_help(dk_parts_hash, dk_make_hash, ARGV.clone)
|
76
|
+
compose_hash, selected_parts, shifted_args = @parts_merger.merge_parts(compose_hash, dk_parts_hash, ARGV.clone)
|
77
|
+
final_args = @yaml_arg_munger.save_yaml_and_adjust_args(compose_hash, shifted_args)
|
78
|
+
run_dk(final_args)
|
371
79
|
else
|
372
|
-
|
373
|
-
end
|
374
|
-
|
375
|
-
end
|
376
|
-
|
377
|
-
def run_dk_set_context()
|
378
|
-
world_settings = get_world_settings_hash()
|
379
|
-
unless world_settings[:world_path] and File.directory?(world_settings[:world_path])
|
380
|
-
@logger.error "no world path set."
|
80
|
+
@logger.error "no docker configuration found"
|
381
81
|
exit 1
|
382
82
|
end
|
383
83
|
|
384
|
-
# read folder from world path (aka. context)
|
385
|
-
all_dir = Dir.chdir(world_settings[:world_path]) do
|
386
|
-
Dir.glob('*').select { |f| File.directory? f and f != "common" }
|
387
|
-
end
|
388
|
-
selected_dir = pick_single_result(all_dir.collect {|f| [f]}, "select context").first
|
389
|
-
world_settings[:context] = selected_dir
|
390
|
-
save_world_settings(world_settings)
|
391
|
-
|
392
|
-
@logger.puts "world set!"
|
393
|
-
exit
|
394
|
-
end
|
395
|
-
|
396
|
-
#
|
397
|
-
# Run: SET PARTS
|
398
|
-
#
|
399
|
-
|
400
|
-
def run_dk_set_parts()
|
401
|
-
parts = ARGV[1..]
|
402
|
-
filepath = get_save_parts_filepath()
|
403
|
-
if parts.any?
|
404
|
-
tempfile = File.new(filepath, 'w')
|
405
|
-
tempfile.write(ARGV[1..].to_yaml) # write it to the tempfile
|
406
|
-
tempfile.close
|
407
|
-
else
|
408
|
-
if File.exist?(filepath)
|
409
|
-
File.delete(filepath)
|
410
|
-
@logger.info "parts cleared"
|
411
|
-
else
|
412
|
-
print_set_parts_help()
|
413
|
-
end
|
414
|
-
end
|
415
|
-
exit
|
416
|
-
end
|
417
|
-
|
418
|
-
#
|
419
|
-
# Run: MAKE
|
420
|
-
#
|
421
|
-
|
422
|
-
def run_dk_make(compose_args, dk_make_hash, dk_parts_hash, selected_part_keys)
|
423
|
-
# print help?
|
424
|
-
no_make_command = (compose_args.count == 3)
|
425
|
-
if no_make_command
|
426
|
-
print_make_help(dk_parts_hash, dk_make_hash)
|
427
|
-
else
|
428
|
-
|
429
|
-
#
|
430
|
-
# supports running multiple commands in a row
|
431
|
-
# ex. dk make down up
|
432
|
-
#
|
433
|
-
|
434
|
-
make_commands = compose_args[3..]
|
435
|
-
make_commands.each_with_index do |key, i|
|
436
|
-
|
437
|
-
if not dk_make_hash.has_key?(key)
|
438
|
-
@logger.error "#{key} - command not found"
|
439
|
-
exit 1
|
440
|
-
else
|
441
|
-
|
442
|
-
all_commands = dk_make_hash[key]["commands"]
|
443
|
-
|
444
|
-
#
|
445
|
-
# all commands run in a subprocess except the last one, so
|
446
|
-
# the last command can run in the forground and be
|
447
|
-
# interactive (ex. dk make down up bash)
|
448
|
-
#
|
449
|
-
|
450
|
-
# construct last command
|
451
|
-
last_cmd = if make_commands.length == i+1
|
452
|
-
all_commands.pop
|
453
|
-
else
|
454
|
-
nil
|
455
|
-
end
|
456
|
-
|
457
|
-
# run background commands
|
458
|
-
all_commands.each do |c|
|
459
|
-
cmd = prep_make_command(c, selected_part_keys)
|
460
|
-
`#{cmd}` # run in sub-process
|
461
|
-
end
|
462
|
-
|
463
|
-
# run last command in foreground
|
464
|
-
if last_cmd
|
465
|
-
cmd = prep_make_command(last_cmd, selected_part_keys)
|
466
|
-
exec(cmd)
|
467
|
-
end
|
468
|
-
end
|
469
|
-
end
|
470
|
-
|
471
|
-
end
|
472
|
-
end
|
473
|
-
|
474
|
-
def prep_make_command(c, selected_part_keys)
|
475
|
-
c = interpolate_parts_into_command(c, selected_part_keys)
|
476
|
-
|
477
|
-
# logging
|
478
|
-
@logger.puts "" if $stdout.isatty
|
479
|
-
@logger.wait(c)
|
480
|
-
cmd = "cd #{@working_dir} && #{c}"
|
481
|
-
end
|
482
|
-
|
483
|
-
def interpolate_parts_into_command(cmd, selected_part_keys)
|
484
|
-
if selected_part_keys.any?
|
485
|
-
parts = selected_part_keys.join(' ')
|
486
|
-
return cmd.gsub("cl dk", "cl dk #{parts}")
|
487
|
-
end
|
488
|
-
return cmd
|
489
84
|
end
|
490
85
|
|
491
86
|
#
|
@@ -494,32 +89,4 @@ end
|
|
494
89
|
|
495
90
|
@working_dir = ENV['CL_WORKING_DIR'] # passed through cl-magic to here
|
496
91
|
|
497
|
-
|
498
|
-
case ARGV.first
|
499
|
-
when "set-world"
|
500
|
-
run_dk_set_world()
|
501
|
-
when "set-context"
|
502
|
-
run_dk_set_context()
|
503
|
-
when "set-parts"
|
504
|
-
run_dk_set_parts()
|
505
|
-
else
|
506
|
-
compose_hash, dk_parts_hash, dk_make_hash = get_base_compose_parts_and_make_hashes()
|
507
|
-
if compose_hash
|
508
|
-
|
509
|
-
# parts & args
|
510
|
-
saved_part_keys = get_saved_parts(dk_parts_hash)
|
511
|
-
compose_args, selected_part_keys = merge_parts_save_and_prep_args(compose_hash, dk_parts_hash, dk_make_hash, saved_part_keys)
|
512
|
-
|
513
|
-
# sub-command
|
514
|
-
case compose_args[2]
|
515
|
-
when "make"
|
516
|
-
all_part_keys = selected_part_keys + saved_part_keys
|
517
|
-
run_dk_make(compose_args, dk_make_hash, dk_parts_hash, all_part_keys)
|
518
|
-
else
|
519
|
-
run_dk(compose_args)
|
520
|
-
end
|
521
|
-
else
|
522
|
-
@logger.error "no docker configuration found"
|
523
|
-
exit 1
|
524
|
-
end
|
525
|
-
end
|
92
|
+
do_work()
|
@@ -0,0 +1,174 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# cli for your compose projects
|
3
|
+
require 'optparse'
|
4
|
+
require 'optparse/subcommand'
|
5
|
+
|
6
|
+
require 'cl/magic/common/common_options.rb'
|
7
|
+
require 'cl/magic/common/logging.rb'
|
8
|
+
|
9
|
+
require_relative 'dk/help_printer'
|
10
|
+
require_relative 'dk/yaml_arg_munger'
|
11
|
+
require_relative 'dk/world_settings'
|
12
|
+
require_relative 'dk/parts_merger'
|
13
|
+
|
14
|
+
@logger = get_logger()
|
15
|
+
@cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
|
16
|
+
|
17
|
+
def print_make_help(dk_parts_hash, dk_make_hash)
|
18
|
+
if $stdout.isatty
|
19
|
+
puts ""
|
20
|
+
puts "Usage: dk make [DK_PARTS] COMMAND"
|
21
|
+
puts ""
|
22
|
+
puts "Make commands designed to make your developer experience more turnkey"
|
23
|
+
puts ""
|
24
|
+
puts "Parts:"
|
25
|
+
dk_parts_hash.keys.each do |key|
|
26
|
+
@help_printer.print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
27
|
+
end
|
28
|
+
puts ""
|
29
|
+
puts "Commands:"
|
30
|
+
dk_make_hash.keys.each do |key|
|
31
|
+
@help_printer.print_dk_help_line(key, dk_make_hash[key].fetch('help'))
|
32
|
+
end
|
33
|
+
puts ""
|
34
|
+
else
|
35
|
+
dk_make_hash.keys.each do |key|
|
36
|
+
puts key
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_dk_make(final_args, dk_make_hash, dk_parts_hash, selected_parts)
|
42
|
+
|
43
|
+
# print help?
|
44
|
+
no_make_command = (final_args.count == 2)
|
45
|
+
if no_make_command
|
46
|
+
print_make_help(dk_parts_hash, dk_make_hash)
|
47
|
+
else
|
48
|
+
|
49
|
+
#
|
50
|
+
# supports running multiple commands in a row
|
51
|
+
# ex. dk make down up
|
52
|
+
#
|
53
|
+
|
54
|
+
make_commands = final_args[2..]
|
55
|
+
make_commands.each_with_index do |key, i|
|
56
|
+
|
57
|
+
if not dk_make_hash.has_key?(key)
|
58
|
+
@logger.error "#{key} - command not found"
|
59
|
+
exit 1
|
60
|
+
else
|
61
|
+
|
62
|
+
all_commands = dk_make_hash[key]["commands"]
|
63
|
+
|
64
|
+
#
|
65
|
+
# all commands run in a subprocess except the last one, so
|
66
|
+
# the last command can run in the forground and be
|
67
|
+
# interactive (ex. dk make down up bash)
|
68
|
+
#
|
69
|
+
|
70
|
+
# construct last command
|
71
|
+
last_cmd = if make_commands.length == i+1
|
72
|
+
all_commands.pop
|
73
|
+
else
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
# run background commands
|
78
|
+
all_commands.each do |c|
|
79
|
+
cmd = prep_make_command(c, selected_parts)
|
80
|
+
`#{cmd}` # run in sub-process
|
81
|
+
end
|
82
|
+
|
83
|
+
# run last command in foreground
|
84
|
+
if last_cmd
|
85
|
+
cmd = prep_make_command(last_cmd, selected_parts)
|
86
|
+
exec(cmd)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def prep_make_command(c, selected_parts)
|
95
|
+
# logging
|
96
|
+
@logger.puts "" if $stdout.isatty
|
97
|
+
@logger.wait(c.gsub("cl dk", "dk"))
|
98
|
+
|
99
|
+
# run command
|
100
|
+
c = interpolate_parts_into_command(c, selected_parts)
|
101
|
+
cmd = "cd #{@working_dir} && #{c}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def interpolate_parts_into_command(cmd, selected_parts)
|
105
|
+
cmd = "cl #{cmd}" if cmd.start_with?("dk")
|
106
|
+
|
107
|
+
# subcommands: don't need interpolated parts
|
108
|
+
['parts', 'make', 'make-world', 'world'].each do |subcommand|
|
109
|
+
return cmd if cmd.start_with?("cl dk #{subcommand}")
|
110
|
+
end
|
111
|
+
|
112
|
+
if selected_parts.any?
|
113
|
+
parts = selected_parts.join(' ')
|
114
|
+
if cmd.include? "cl dk make"
|
115
|
+
return cmd.gsub("cl dk make", "cl dk make #{parts}")
|
116
|
+
else
|
117
|
+
return cmd.gsub("cl dk", "cl dk #{parts}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return cmd
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# Features
|
125
|
+
#
|
126
|
+
|
127
|
+
def do_work()
|
128
|
+
|
129
|
+
# utils
|
130
|
+
@help_printer = HelpPrinter.new(@logger)
|
131
|
+
@world_settings = WorldSettings.new(@working_dir)
|
132
|
+
@yaml_arg_munger = YamlArgMunger.new(@working_dir, @world_settings)
|
133
|
+
@parts_merger = PartsMerger.new(@working_dir, @yaml_arg_munger, @help_printer, @logger)
|
134
|
+
|
135
|
+
# world files
|
136
|
+
compose_hash, dk_parts_hash, dk_make_hash = @yaml_arg_munger.get_base_compose_parts_and_make_hashes()
|
137
|
+
if compose_hash
|
138
|
+
compose_hash, selected_parts, shifted_args = @parts_merger.merge_parts(compose_hash, dk_parts_hash, ARGV.clone)
|
139
|
+
final_args = @yaml_arg_munger.save_yaml_and_adjust_args(compose_hash, shifted_args)
|
140
|
+
run_dk_make(final_args, dk_make_hash, dk_parts_hash, selected_parts)
|
141
|
+
else
|
142
|
+
@logger.error "no docker configuration found"
|
143
|
+
exit 1
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# Options
|
150
|
+
#
|
151
|
+
|
152
|
+
options = {}
|
153
|
+
global_banner = <<DOC
|
154
|
+
|
155
|
+
Cli for your compose projects
|
156
|
+
|
157
|
+
Usage: #{@cl_cmd_name} [options]
|
158
|
+
|
159
|
+
DOC
|
160
|
+
|
161
|
+
global = OptionParser.new do |g|
|
162
|
+
g.banner = global_banner
|
163
|
+
add_help_and_verbose(g)
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Run
|
168
|
+
#
|
169
|
+
|
170
|
+
@working_dir = ENV['CL_WORKING_DIR'] # passed through cl-magic to here
|
171
|
+
|
172
|
+
global.parse(ARGV)
|
173
|
+
|
174
|
+
do_work()
|