cl-magic 0.3.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 +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
|