cl-magic 0.4.0 → 1.2.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 +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()
|