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