cl-magic 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +47 -0
- data/README.md +211 -0
- data/bin/cl +17 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/cl-magic.gemspec +38 -0
- data/lib/cl/magic/cl +97 -0
- data/lib/cl/magic/cl-auth +109 -0
- data/lib/cl/magic/cl-aws-okta-auth +52 -0
- data/lib/cl/magic/cl-aws-okta-env +79 -0
- data/lib/cl/magic/cl-dk +402 -0
- data/lib/cl/magic/cl-envkey +70 -0
- data/lib/cl/magic/cl-gc-sql +135 -0
- data/lib/cl/magic/cl-gc-tags +171 -0
- data/lib/cl/magic/cl-glab-commit +68 -0
- data/lib/cl/magic/cl-history +44 -0
- data/lib/cl/magic/cl-kube-cp +99 -0
- data/lib/cl/magic/cl-kube-deployment +120 -0
- data/lib/cl/magic/cl-kube-ktx +60 -0
- data/lib/cl/magic/cl-kube-logs +114 -0
- data/lib/cl/magic/cl-kube-restart +84 -0
- data/lib/cl/magic/cl-kube-search +111 -0
- data/lib/cl/magic/cl-kube-search-all +97 -0
- data/lib/cl/magic/cl-kube-ssh +94 -0
- data/lib/cl/magic/cl-poll +51 -0
- data/lib/cl/magic/cl-sandbox +49 -0
- data/lib/cl/magic/cl-vault +84 -0
- data/lib/cl/magic/common/common_options.rb +16 -0
- data/lib/cl/magic/common/gcloud.rb +71 -0
- data/lib/cl/magic/common/kubectl.rb +236 -0
- data/lib/cl/magic/common/logging.rb +25 -0
- data/lib/cl/magic/common/parse_and_pick.rb +81 -0
- data/lib/cl/magic/version.rb +7 -0
- data/lib/cl/magic.rb +9 -0
- metadata +180 -0
data/lib/cl/magic/cl-dk
ADDED
@@ -0,0 +1,402 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
require 'tty-command'
|
5
|
+
require 'tempfile'
|
6
|
+
|
7
|
+
require 'cl/magic/common/common_options.rb'
|
8
|
+
require 'cl/magic/common/logging.rb'
|
9
|
+
|
10
|
+
@logger = get_logger()
|
11
|
+
|
12
|
+
#
|
13
|
+
# Util Methods
|
14
|
+
#
|
15
|
+
|
16
|
+
def get_base_compose_hash()
|
17
|
+
cmd = "cd #{@working_dir} && docker compose config"
|
18
|
+
return YAML.load(`#{cmd}`)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_repo_basename()
|
22
|
+
command = "cd #{@working_dir} && basename $(git remote get-url origin 2> /dev/null) .git"
|
23
|
+
return TTY::Command.new(:printer => :null).run(command).out.gsub('.git', '').strip.chomp
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_dk_world_project_path()
|
27
|
+
repo_basename = get_repo_basename()
|
28
|
+
return "dk-world/#{repo_basename}" if repo_basename
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_save_parts_filepath()
|
33
|
+
return File.join(@working_dir, ".cl-dk-parts.yml")
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Print Help Methods
|
38
|
+
#
|
39
|
+
|
40
|
+
def print_dk_help_line(key, help)
|
41
|
+
if help.nil?
|
42
|
+
@logger.puts("#{key.ljust(15, ' ')} ???no help???")
|
43
|
+
else
|
44
|
+
key = key.ljust(15, ' ')
|
45
|
+
help_parts = help.split(";")
|
46
|
+
|
47
|
+
# first line
|
48
|
+
@logger.puts(key, help_parts.shift)
|
49
|
+
|
50
|
+
# following lines
|
51
|
+
padding = "".ljust(15, ' ')
|
52
|
+
help_parts.each do |p|
|
53
|
+
@logger.puts(padding, p)
|
54
|
+
end
|
55
|
+
puts("") if help.end_with?(";")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def print_dk_help(dk_parts_hash, dk_make_hash, args)
|
60
|
+
no_args = args.empty?()
|
61
|
+
asked_for_help = args.include?('--help')
|
62
|
+
has_dk_commands = dk_parts_hash.keys.any?
|
63
|
+
|
64
|
+
if no_args or asked_for_help
|
65
|
+
if has_dk_commands
|
66
|
+
puts ""
|
67
|
+
puts "Usage: dk [DK_PARTS] [COMPOSE_OPTIONS] COMPOSE_COMMAND"
|
68
|
+
puts ""
|
69
|
+
puts "Run docker compose while munging yamls in sophisticated ways."
|
70
|
+
puts ""
|
71
|
+
if get_repo_basename
|
72
|
+
puts "PROJ INFO:"
|
73
|
+
puts " - Repo basename: #{get_repo_basename}"
|
74
|
+
puts " - World filepath: #{File.join(@working_dir, get_dk_world_project_path())}"
|
75
|
+
puts ""
|
76
|
+
end
|
77
|
+
puts "PROJ PARTS:"
|
78
|
+
dk_parts_hash.keys.each do |key|
|
79
|
+
print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
80
|
+
end
|
81
|
+
puts ""
|
82
|
+
puts "YML TOKENS"
|
83
|
+
puts " - <dk-remove>"
|
84
|
+
puts " - <dk-replace>"
|
85
|
+
puts " - <dk-project-path>"
|
86
|
+
puts " - <dk-world-path>"
|
87
|
+
puts " - <dk-working-path>"
|
88
|
+
puts ""
|
89
|
+
puts "ADDITIONAL TURNKEY COMMANDS:"
|
90
|
+
puts " - dk make"
|
91
|
+
puts " - dk save-parts"
|
92
|
+
puts ""
|
93
|
+
puts "-------------------------"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def print_make_help(dk_parts_hash, dk_make_hash)
|
99
|
+
puts ""
|
100
|
+
puts "Usage: dk [DK_PARTS] make COMMAND"
|
101
|
+
puts ""
|
102
|
+
puts "Make commands designed to make your developer experience more turnkey"
|
103
|
+
puts ""
|
104
|
+
puts "Parts:"
|
105
|
+
dk_parts_hash.keys.each do |key|
|
106
|
+
print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
107
|
+
end
|
108
|
+
puts ""
|
109
|
+
puts "Commands:"
|
110
|
+
dk_make_hash.keys.each do |key|
|
111
|
+
print_dk_help_line(key, dk_make_hash[key].fetch('help'))
|
112
|
+
end
|
113
|
+
puts ""
|
114
|
+
end
|
115
|
+
|
116
|
+
def print_save_parts_help(dk_parts_hash)
|
117
|
+
puts ""
|
118
|
+
puts "Usage: dk [DK_PARTS] save-parts"
|
119
|
+
puts ""
|
120
|
+
puts "Save parts in project and apply every time"
|
121
|
+
puts ""
|
122
|
+
puts "Parts:"
|
123
|
+
dk_parts_hash.keys.each do |key|
|
124
|
+
print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
|
125
|
+
end
|
126
|
+
puts ""
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# Yaml Merging
|
131
|
+
#
|
132
|
+
|
133
|
+
class ::Hash
|
134
|
+
def dk_merge(second)
|
135
|
+
merger = proc { |_, v1, v2|
|
136
|
+
if Hash === v1 && Hash === v2
|
137
|
+
v1.merge(v2, &merger)
|
138
|
+
else
|
139
|
+
if Array === v1 && Array === v2
|
140
|
+
if v2.first=="<dk-replace>"
|
141
|
+
v2[1..-1] # everything but the first item
|
142
|
+
else
|
143
|
+
v1 | v2 # union arrays
|
144
|
+
end
|
145
|
+
else
|
146
|
+
if [:undefined, nil, :nil].include?(v2)
|
147
|
+
v1
|
148
|
+
else
|
149
|
+
v2
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
}
|
154
|
+
merge(second.to_h, &merger)
|
155
|
+
end
|
156
|
+
def dk_reject!(&blk)
|
157
|
+
self.each do |k, v|
|
158
|
+
v.dk_reject!(&blk) if v.is_a?(Hash)
|
159
|
+
self.delete(k) if blk.call(k, v)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def dk_merge_and_remove(compose_hash, yml_hash)
|
165
|
+
# remove help & merge
|
166
|
+
clean_yml = yml_hash.clone
|
167
|
+
clean_yml.delete('help')
|
168
|
+
return compose_hash.dk_merge(clean_yml).dk_reject! { |k, v| v=='<dk-remove>' }
|
169
|
+
end
|
170
|
+
|
171
|
+
def merge_world_files(compose_hash, show_help=false)
|
172
|
+
dk_proj_path = get_dk_world_project_path()
|
173
|
+
if dk_proj_path
|
174
|
+
print_dk_help_line("dk-project-path", "#{dk_proj_path}") if show_help
|
175
|
+
|
176
|
+
Dir.glob("#{dk_proj_path}/*.yml").sort.each do |filepath|
|
177
|
+
print_dk_help_line("dk-world", "#{filepath}") if show_help
|
178
|
+
|
179
|
+
# read file and replace
|
180
|
+
contents = File.read(filepath)
|
181
|
+
contents.gsub!('<dk-world-path>', File.join(Dir.pwd, "dk-world"))
|
182
|
+
contents.gsub!('<dk-project-path>', File.join(Dir.pwd, dk_proj_path))
|
183
|
+
contents.gsub!('<dk-working-path>', @working_dir)
|
184
|
+
|
185
|
+
# yml merge
|
186
|
+
yml_hash = YAML.load(contents)
|
187
|
+
compose_hash = dk_merge_and_remove(compose_hash, yml_hash)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
return compose_hash
|
191
|
+
end
|
192
|
+
|
193
|
+
def get_saved_parts(dk_parts_hash)
|
194
|
+
saved_part_keys = []
|
195
|
+
filepath = get_save_parts_filepath()
|
196
|
+
|
197
|
+
# merge
|
198
|
+
if File.exist?(filepath)
|
199
|
+
saved_parts = YAML.load_file(filepath)
|
200
|
+
saved_parts.each do |potential_part_key|
|
201
|
+
dk_part = dk_parts_hash.fetch(potential_part_key, nil) # yml detail
|
202
|
+
if dk_part
|
203
|
+
saved_part_keys << potential_part_key
|
204
|
+
else
|
205
|
+
@logger.error "invalid saved part: #{potential_part_key}"
|
206
|
+
exit 1
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
return saved_part_keys
|
211
|
+
end
|
212
|
+
|
213
|
+
def merge_parts_save_and_prep_args(compose_hash, dk_parts_hash, dk_make_hash, saved_part_keys)
|
214
|
+
tempfile = File.new(File.join(@working_dir, ".cl-dk.yml"), 'w')
|
215
|
+
args = ARGV.clone
|
216
|
+
|
217
|
+
# dk help
|
218
|
+
print_dk_help(dk_parts_hash, dk_make_hash, args)
|
219
|
+
|
220
|
+
def print_and_merge_part(part_key, dk_part, compose_hash)
|
221
|
+
# print
|
222
|
+
help_str = dk_part.fetch('help')
|
223
|
+
print_dk_help_line("#{part_key}", "#{help_str ? '- ' + help_str : ''}") if dk_part.keys.any?
|
224
|
+
|
225
|
+
# merge
|
226
|
+
return dk_merge_and_remove(compose_hash, dk_part)
|
227
|
+
end
|
228
|
+
|
229
|
+
# saved parts
|
230
|
+
saved_part_keys.each do |potential_part_key|
|
231
|
+
dk_part = dk_parts_hash.fetch(potential_part_key, nil) # yml detail
|
232
|
+
compose_hash = print_and_merge_part(potential_part_key, dk_part, compose_hash) if dk_part
|
233
|
+
end
|
234
|
+
|
235
|
+
# arg parts
|
236
|
+
selected_part_keys = []
|
237
|
+
while true
|
238
|
+
potential_part_key = args.first
|
239
|
+
dk_part = dk_parts_hash.fetch(potential_part_key, nil) # yml detail
|
240
|
+
if dk_part
|
241
|
+
|
242
|
+
# unless already applied
|
243
|
+
unless saved_part_keys.include?(potential_part_key)
|
244
|
+
compose_hash = print_and_merge_part(potential_part_key, dk_part, compose_hash)
|
245
|
+
end
|
246
|
+
selected_part_keys << potential_part_key
|
247
|
+
args.shift # remove part arg
|
248
|
+
else
|
249
|
+
break
|
250
|
+
end
|
251
|
+
end
|
252
|
+
puts "" # tailing line break
|
253
|
+
tempfile.write(compose_hash.to_yaml) # write it to the tempfile
|
254
|
+
|
255
|
+
# clone args
|
256
|
+
args = args.clone
|
257
|
+
|
258
|
+
# remove existing '-f' flag, if needed
|
259
|
+
file_flag_index = args.index('-f')
|
260
|
+
if file_flag_index==0
|
261
|
+
args.delete_at(file_flag_index)
|
262
|
+
args.delete_at(file_flag_index)
|
263
|
+
end
|
264
|
+
args.unshift('-f', tempfile.path) # add new '-f' flag
|
265
|
+
|
266
|
+
tempfile.close
|
267
|
+
return args, selected_part_keys
|
268
|
+
end
|
269
|
+
|
270
|
+
#
|
271
|
+
# Run: DK
|
272
|
+
#
|
273
|
+
|
274
|
+
def run_dk(compose_args)
|
275
|
+
cmd = "cd #{@working_dir} && docker compose #{compose_args.join(' ')}"
|
276
|
+
exec(cmd)
|
277
|
+
end
|
278
|
+
|
279
|
+
#
|
280
|
+
# Run: SAVE PARTS
|
281
|
+
#
|
282
|
+
|
283
|
+
def run_dk_save_parts(compose_args, dk_parts_hash, selected_part_keys)
|
284
|
+
filepath = get_save_parts_filepath()
|
285
|
+
if selected_part_keys.any?
|
286
|
+
tempfile = File.new(filepath, 'w')
|
287
|
+
tempfile.write(selected_part_keys.to_yaml) # write it to the tempfile
|
288
|
+
else
|
289
|
+
if File.exist?(filepath)
|
290
|
+
File.delete(filepath)
|
291
|
+
@logger.info "parts cleared"
|
292
|
+
else
|
293
|
+
print_save_parts_help(dk_parts_hash)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# Run: MAKE
|
300
|
+
#
|
301
|
+
|
302
|
+
def run_dk_make(compose_args, dk_make_hash, dk_parts_hash, selected_part_keys)
|
303
|
+
# print help?
|
304
|
+
no_make_command = (compose_args.count == 3)
|
305
|
+
if no_make_command
|
306
|
+
print_make_help(dk_parts_hash, dk_make_hash)
|
307
|
+
else
|
308
|
+
|
309
|
+
#
|
310
|
+
# supports running multiple commands in a row
|
311
|
+
# ex. dk make down up
|
312
|
+
#
|
313
|
+
|
314
|
+
make_commands = compose_args[3..]
|
315
|
+
make_commands.each_with_index do |key, i|
|
316
|
+
|
317
|
+
if not dk_make_hash.has_key?(key)
|
318
|
+
puts "#{key} - command not found"
|
319
|
+
exit 1
|
320
|
+
else
|
321
|
+
|
322
|
+
all_commands = dk_make_hash[key]["commands"]
|
323
|
+
|
324
|
+
#
|
325
|
+
# all commands run in a subprocess except the last one, so
|
326
|
+
# the last command can run in the forground and be
|
327
|
+
# interactive (ex. dk make down up bash)
|
328
|
+
#
|
329
|
+
|
330
|
+
# construct last command
|
331
|
+
last_cmd = if make_commands.length == i+1
|
332
|
+
all_commands.pop
|
333
|
+
else
|
334
|
+
nil
|
335
|
+
end
|
336
|
+
|
337
|
+
# run background commands
|
338
|
+
all_commands.each do |c|
|
339
|
+
cmd = prep_make_command(c, selected_part_keys)
|
340
|
+
`#{cmd}` # run in sub-process
|
341
|
+
end
|
342
|
+
|
343
|
+
# run last command in foreground
|
344
|
+
if last_cmd
|
345
|
+
cmd = prep_make_command(last_cmd, selected_part_keys)
|
346
|
+
exec(cmd)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def prep_make_command(c, selected_part_keys)
|
355
|
+
c = interpolate_parts_into_command(c, selected_part_keys)
|
356
|
+
|
357
|
+
# logging
|
358
|
+
@logger.puts ""
|
359
|
+
@logger.wait(c)
|
360
|
+
cmd = "cd #{@working_dir} && #{c}"
|
361
|
+
end
|
362
|
+
|
363
|
+
def interpolate_parts_into_command(cmd, selected_part_keys)
|
364
|
+
if selected_part_keys.any?
|
365
|
+
parts = selected_part_keys.join(' ')
|
366
|
+
return cmd.gsub("cl dk", "cl dk #{parts}")
|
367
|
+
end
|
368
|
+
return cmd
|
369
|
+
end
|
370
|
+
|
371
|
+
#
|
372
|
+
# Main
|
373
|
+
#
|
374
|
+
|
375
|
+
@working_dir = ENV['CL_WORKING_DIR'] # passed through cl-magic to here
|
376
|
+
|
377
|
+
# get compose settings
|
378
|
+
compose_hash = get_base_compose_hash()
|
379
|
+
if compose_hash
|
380
|
+
|
381
|
+
# world
|
382
|
+
compose_hash = merge_world_files(compose_hash, show_help=ARGV.include?("--help"))
|
383
|
+
|
384
|
+
# x-dk fragments
|
385
|
+
dk_parts_hash = compose_hash['x-dk-parts'] ? compose_hash.delete('x-dk-parts') : {}
|
386
|
+
dk_make_hash = compose_hash['x-dk-make'] ? compose_hash.delete('x-dk-make') : {}
|
387
|
+
|
388
|
+
# parts
|
389
|
+
saved_part_keys = get_saved_parts(dk_parts_hash)
|
390
|
+
compose_args, selected_part_keys = merge_parts_save_and_prep_args(compose_hash, dk_parts_hash, dk_make_hash, saved_part_keys)
|
391
|
+
|
392
|
+
# sub-command
|
393
|
+
case compose_args[2]
|
394
|
+
when "make"
|
395
|
+
all_part_keys = selected_part_keys + saved_part_keys
|
396
|
+
run_dk_make(compose_args, dk_make_hash, dk_parts_hash, all_part_keys)
|
397
|
+
when "save-parts"
|
398
|
+
run_dk_save_parts(compose_args, dk_parts_hash, selected_part_keys)
|
399
|
+
else
|
400
|
+
run_dk(compose_args)
|
401
|
+
end
|
402
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/subcommand'
|
4
|
+
require 'tty-command'
|
5
|
+
require 'tty-prompt'
|
6
|
+
|
7
|
+
require 'cl/magic/common/common_options.rb'
|
8
|
+
require 'cl/magic/common/logging.rb'
|
9
|
+
require 'cl/magic/common/gcloud.rb'
|
10
|
+
require 'cl/magic/common/kubectl.rb'
|
11
|
+
|
12
|
+
@logger = get_logger()
|
13
|
+
@cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
|
14
|
+
|
15
|
+
#
|
16
|
+
# Features
|
17
|
+
#
|
18
|
+
|
19
|
+
def do_work(options)
|
20
|
+
envkey_str = `cd #{@working_dir} && envkey-source`
|
21
|
+
envkey_array = envkey_str.split(' ')
|
22
|
+
result = if options[:filter]
|
23
|
+
envkey_array.select {|o|
|
24
|
+
o.gsub("'","").start_with? options[:filter]
|
25
|
+
}
|
26
|
+
else
|
27
|
+
envkey_array
|
28
|
+
end
|
29
|
+
puts result
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Options
|
34
|
+
#
|
35
|
+
|
36
|
+
options = {}
|
37
|
+
global_banner = <<DOC
|
38
|
+
|
39
|
+
A sandbox to try things
|
40
|
+
|
41
|
+
Usage: #{@cl_cmd_name} [options]
|
42
|
+
|
43
|
+
DOC
|
44
|
+
|
45
|
+
global = OptionParser.new do |g|
|
46
|
+
g.banner = global_banner
|
47
|
+
add_help_and_verbose(g)
|
48
|
+
|
49
|
+
g.on("-f", "--filter string", "filter by string (i.e. starts with)") do |v|
|
50
|
+
options[:filter] = v
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Run
|
56
|
+
#
|
57
|
+
|
58
|
+
@working_dir = ENV['CL_WORKING_DIR'] # passed through cl-magic to here
|
59
|
+
global.parse(ARGV)
|
60
|
+
|
61
|
+
# display full command
|
62
|
+
if options[:filter]
|
63
|
+
write_history("""#{@cl_cmd_name} connect \\
|
64
|
+
--filter=#{options[:filter]}
|
65
|
+
""")
|
66
|
+
else
|
67
|
+
write_history("""#{@cl_cmd_name}""")
|
68
|
+
end
|
69
|
+
|
70
|
+
do_work(options)
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/subcommand'
|
4
|
+
require 'tty-command'
|
5
|
+
require 'tty-prompt'
|
6
|
+
|
7
|
+
require 'cl/magic/common/common_options.rb'
|
8
|
+
require 'cl/magic/common/logging.rb'
|
9
|
+
require 'cl/magic/common/gcloud.rb'
|
10
|
+
|
11
|
+
@logger = get_logger()
|
12
|
+
@cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
|
13
|
+
|
14
|
+
#
|
15
|
+
# Features
|
16
|
+
#
|
17
|
+
|
18
|
+
def set_project_instance_and_user(options)
|
19
|
+
project = pick_gcloud_project(options[:project])
|
20
|
+
instance = pick_single_result(get_sql_instances, 'Pick sql instance', options[:instance])
|
21
|
+
user = pick_single_result(get_sql_users(instance), 'Pick sql user', options[:user])
|
22
|
+
return project, instance, user
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_password(options)
|
26
|
+
project, instance, user = set_project_instance_and_user(options)
|
27
|
+
|
28
|
+
# display full command
|
29
|
+
write_history("""#{@cl_cmd_name} set-password \\
|
30
|
+
--project=#{project.first} \\
|
31
|
+
--instance=#{instance.first} \\
|
32
|
+
--user=#{user.first}
|
33
|
+
""")
|
34
|
+
|
35
|
+
# run
|
36
|
+
@logger.puts ""
|
37
|
+
cmd = "gcloud sql users set-password #{user.first} --instance=#{instance.first} --prompt-for-password"
|
38
|
+
@logger.wait cmd
|
39
|
+
exec(cmd)
|
40
|
+
end
|
41
|
+
|
42
|
+
def connect(options)
|
43
|
+
project, instance, user = set_project_instance_and_user(options)
|
44
|
+
database = pick_single_result(get_sql_databases(instance), "Which database?")
|
45
|
+
|
46
|
+
# display full command
|
47
|
+
write_history("""#{@cl_cmd_name} connect \\
|
48
|
+
--project=#{project.first} \\
|
49
|
+
--instance=#{instance.first} \\
|
50
|
+
--user=#{user.first} \\
|
51
|
+
--database=#{database.first}
|
52
|
+
""")
|
53
|
+
|
54
|
+
# run
|
55
|
+
@logger.puts ""
|
56
|
+
cmd = "gcloud sql connect #{instance.first} --user=#{user.first} --database=#{database.first}"
|
57
|
+
@logger.wait cmd
|
58
|
+
exec(cmd)
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Options
|
63
|
+
#
|
64
|
+
|
65
|
+
options = {}
|
66
|
+
global_banner = <<DOC
|
67
|
+
|
68
|
+
A tool for everything google cloud sql
|
69
|
+
|
70
|
+
Usage: #{@cl_cmd_name} [options]
|
71
|
+
|
72
|
+
DOC
|
73
|
+
|
74
|
+
set_password_banner = <<DOC
|
75
|
+
|
76
|
+
Set the password for a sql user
|
77
|
+
|
78
|
+
Usage: #{@cl_cmd_name} set-password [options]
|
79
|
+
|
80
|
+
DOC
|
81
|
+
|
82
|
+
connect_banner = <<DOC
|
83
|
+
|
84
|
+
Connect to a sql database
|
85
|
+
|
86
|
+
Usage: #{@cl_cmd_name} connect [options]
|
87
|
+
|
88
|
+
DOC
|
89
|
+
|
90
|
+
def add_project_instance_and_user_options(s, options)
|
91
|
+
s.on("-p", "--project PROJECT", "google cloud project") do |v|
|
92
|
+
options[:project] = v
|
93
|
+
end
|
94
|
+
s.on("-i", "--instance INSTANCE", "google cloud sql instance") do |v|
|
95
|
+
options[:instance] = v
|
96
|
+
end
|
97
|
+
s.on("-u", "--user USER", "google cloud sql user") do |v|
|
98
|
+
options[:user] = v
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
global = OptionParser.new do |g|
|
103
|
+
g.banner = global_banner
|
104
|
+
add_help_and_verbose(g)
|
105
|
+
|
106
|
+
g.subcommand 'set-password' do |s|
|
107
|
+
s.banner = set_password_banner
|
108
|
+
options[:action] = :set_password
|
109
|
+
add_project_instance_and_user_options(s, options)
|
110
|
+
end
|
111
|
+
|
112
|
+
g.subcommand 'connect' do |s|
|
113
|
+
s.banner = connect_banner
|
114
|
+
options[:action] = :connect
|
115
|
+
add_project_instance_and_user_options(s, options)
|
116
|
+
s.on("-d", "--database DATABASE", "google cloud sql database name") do |v|
|
117
|
+
options[:user] = v
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Run
|
124
|
+
#
|
125
|
+
|
126
|
+
global.parse(ARGV)
|
127
|
+
|
128
|
+
case options[:action]
|
129
|
+
when :set_password
|
130
|
+
set_password(options)
|
131
|
+
when :connect
|
132
|
+
connect(options)
|
133
|
+
else
|
134
|
+
puts global.parse! %w[--help]
|
135
|
+
end
|