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
@@ -0,0 +1,171 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/subcommand'
|
4
|
+
require 'tty-command'
|
5
|
+
|
6
|
+
require 'cl/magic/common/common_options.rb'
|
7
|
+
require 'cl/magic/common/logging.rb'
|
8
|
+
require 'cl/magic/common/gcloud.rb'
|
9
|
+
require 'cl/magic/common/kubectl.rb'
|
10
|
+
|
11
|
+
@logger = get_logger()
|
12
|
+
@cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
|
13
|
+
|
14
|
+
#
|
15
|
+
# Features
|
16
|
+
#
|
17
|
+
|
18
|
+
def get_full_image_name(options)
|
19
|
+
if options[:image].include?('/')
|
20
|
+
return options[:image]
|
21
|
+
else
|
22
|
+
return "gcr.io/#{options[:project]}/#{options[:image]}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_gcloud_cmd(options)
|
27
|
+
if options[:image].nil?
|
28
|
+
@logger.error("Please provide `-i IMAGE`")
|
29
|
+
exit(1)
|
30
|
+
end
|
31
|
+
full_image_name = get_full_image_name(options)
|
32
|
+
return "gcloud container images list-tags #{full_image_name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_newest_image_digest(options)
|
36
|
+
@logger.info "fetching newest digest"
|
37
|
+
cmd = get_gcloud_cmd(options)
|
38
|
+
cmd += " | sed -n 2p | tr -s ' ' | cut -d ' ' -f 2"
|
39
|
+
@logger.wait cmd
|
40
|
+
out, err = TTY::Command.new(:printer => :null).run("#{cmd}")
|
41
|
+
newest_digest = out.chomp
|
42
|
+
if newest_digest.include? "latest"
|
43
|
+
@logger.info("#{newest_digest} is already the latest")
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
return newest_digest
|
47
|
+
end
|
48
|
+
|
49
|
+
def tag_image(options, image_digest, tag)
|
50
|
+
full_image_name = get_full_image_name(options)
|
51
|
+
@logger.info "tagging", [options[:image], image_digest, tag]
|
52
|
+
cmd = "gcloud container images add-tag --quiet #{full_image_name}:#{image_digest} #{full_image_name}:#{tag}"
|
53
|
+
@logger.wait cmd
|
54
|
+
out, err = TTY::Command.new(:printer => :null).run(cmd)
|
55
|
+
puts out
|
56
|
+
end
|
57
|
+
|
58
|
+
def tag_latest(options)
|
59
|
+
if options[:tag].nil?
|
60
|
+
tag = 'latest'
|
61
|
+
else
|
62
|
+
tag = options[:tag]
|
63
|
+
end
|
64
|
+
|
65
|
+
if options[:image_digest]
|
66
|
+
image_digest = options[:image_digest]
|
67
|
+
else
|
68
|
+
image_digest = get_newest_image_digest(options)
|
69
|
+
@logger.success "Got newest: #{image_digest}"
|
70
|
+
end
|
71
|
+
|
72
|
+
tag_image(options, image_digest, tag)
|
73
|
+
end
|
74
|
+
|
75
|
+
def list_tags(options)
|
76
|
+
cmd = get_gcloud_cmd(options)
|
77
|
+
|
78
|
+
# display full command
|
79
|
+
write_history("""
|
80
|
+
#{@cl_cmd_name} list \\
|
81
|
+
--image=#{options[:image]}
|
82
|
+
--project=#{options[:project]}
|
83
|
+
""")
|
84
|
+
@logger.wait cmd
|
85
|
+
out, err = TTY::Command.new(:printer => :null).run(cmd)
|
86
|
+
puts out
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Options
|
91
|
+
#
|
92
|
+
|
93
|
+
options = {}
|
94
|
+
global_banner = <<DOC
|
95
|
+
|
96
|
+
Work with google cloud tags.
|
97
|
+
|
98
|
+
These are important for local docker development as the latest production image
|
99
|
+
will often be what we pull down to run our compose stacks. Let's make it easier
|
100
|
+
for devs to list and tag images locally.
|
101
|
+
|
102
|
+
Usage: #{@cl_cmd_name} [options]
|
103
|
+
|
104
|
+
DOC
|
105
|
+
|
106
|
+
list_banner = <<DOC
|
107
|
+
|
108
|
+
List all the tags for a google cloud image
|
109
|
+
|
110
|
+
Usage: #{@cl_cmd_name} list [options]
|
111
|
+
|
112
|
+
DOC
|
113
|
+
|
114
|
+
tag_banner = <<DOC
|
115
|
+
|
116
|
+
Tag a google cloud image
|
117
|
+
|
118
|
+
Usage: #{@cl_cmd_name} tag [options]
|
119
|
+
|
120
|
+
DOC
|
121
|
+
|
122
|
+
def add_image_option(parser, options)
|
123
|
+
parser.on("-i", "--image IMAGE", "docker images in google cloud") do |v|
|
124
|
+
options[:image] = v
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
global = OptionParser.new do |g|
|
129
|
+
g.banner = global_banner
|
130
|
+
add_help_and_verbose(g)
|
131
|
+
|
132
|
+
g.subcommand 'list' do |s|
|
133
|
+
s.banner = list_banner
|
134
|
+
options[:action] = :list
|
135
|
+
add_image_option(s, options)
|
136
|
+
|
137
|
+
s.on("-p", "--project NAME", "google cloud project name") do |v|
|
138
|
+
options[:gc_project] = v
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
g.subcommand 'tag' do |s|
|
143
|
+
s.banner = tag_banner
|
144
|
+
options[:action] = :tag
|
145
|
+
add_image_option(s, options)
|
146
|
+
|
147
|
+
s.on("-t", "--tag TAG", "tag name to put on the image in google cloud") do |v|
|
148
|
+
options[:tag] = v
|
149
|
+
end
|
150
|
+
s.on("-d", "--image-digest DIGEST", "image digest to tag") do |v|
|
151
|
+
options[:image_digest] = v
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# Run
|
159
|
+
#
|
160
|
+
|
161
|
+
global.parse(ARGV)
|
162
|
+
|
163
|
+
case options[:action]
|
164
|
+
when :list
|
165
|
+
options[:project] = pick_gcloud_project(options[:project]).first
|
166
|
+
list_tags(options)
|
167
|
+
when :tag
|
168
|
+
tag_latest(options)
|
169
|
+
else
|
170
|
+
puts global.parse! %w[--help]
|
171
|
+
end
|
@@ -0,0 +1,68 @@
|
|
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
|
+
cmd = "glab api /projects/:id/repository/commits/#{options[:commit]} | jq .web_url | xargs open"
|
21
|
+
@logger.info cmd
|
22
|
+
exec("cd #{@working_dir} && #{cmd}")
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Options
|
27
|
+
#
|
28
|
+
|
29
|
+
options = {}
|
30
|
+
global_banner = <<DOC
|
31
|
+
|
32
|
+
A sandbox to try things
|
33
|
+
|
34
|
+
Usage: #{@cl_cmd_name} [options]
|
35
|
+
|
36
|
+
DOC
|
37
|
+
|
38
|
+
global = OptionParser.new do |g|
|
39
|
+
g.banner = global_banner
|
40
|
+
add_help_and_verbose(g)
|
41
|
+
|
42
|
+
g.on("-c", "--commit sha", "the commit you want to view in the browser") do |v|
|
43
|
+
options[:commit] = v
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Run
|
49
|
+
#
|
50
|
+
|
51
|
+
@working_dir = ENV['CL_WORKING_DIR'] # passed through cl-magic to here
|
52
|
+
global.parse(ARGV)
|
53
|
+
|
54
|
+
unless options[:commit]
|
55
|
+
command = "cd #{@working_dir} && git log --oneline | head -c 100000"
|
56
|
+
results = TTY::Command.new(:printer => :null).run(command).collect{|c|
|
57
|
+
parts = c.split(' ')
|
58
|
+
[parts.first, parts[1..].join(' ')]
|
59
|
+
}
|
60
|
+
options[:commit] = pick_single_result(results, "").first
|
61
|
+
puts options[:commit]
|
62
|
+
end
|
63
|
+
|
64
|
+
write_history("""#{@cl_cmd_name} \\
|
65
|
+
--commit=#{options[:commit]} \\
|
66
|
+
""")
|
67
|
+
|
68
|
+
do_work(options)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/subcommand'
|
4
|
+
require 'tty-command'
|
5
|
+
|
6
|
+
require 'cl/magic/common/common_options.rb'
|
7
|
+
require 'cl/magic/common/logging.rb'
|
8
|
+
|
9
|
+
@logger = get_logger()
|
10
|
+
@cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
|
11
|
+
|
12
|
+
#
|
13
|
+
# Features
|
14
|
+
#
|
15
|
+
|
16
|
+
def tail_history(options)
|
17
|
+
exec("tail -n 100 #{Dir.home}/.cl_history")
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Options
|
22
|
+
#
|
23
|
+
|
24
|
+
options = {}
|
25
|
+
global_banner = <<DOC
|
26
|
+
|
27
|
+
History of commands you have run
|
28
|
+
|
29
|
+
Usage: #{@cl_cmd_name} [options]
|
30
|
+
|
31
|
+
DOC
|
32
|
+
|
33
|
+
global = OptionParser.new do |g|
|
34
|
+
g.banner = global_banner
|
35
|
+
add_help_and_verbose(g)
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Run
|
40
|
+
#
|
41
|
+
|
42
|
+
global.parse(ARGV)
|
43
|
+
|
44
|
+
tail_history(options)
|
@@ -0,0 +1,99 @@
|
|
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 upload_file(options)
|
20
|
+
cmd = "cd #{@working_dir} && kubectl -n #{options[:namespace]} -c #{options[:container_name]} cp #{options[:local_filepath]} #{options[:pod_name]}:#{options[:remote_path]}"
|
21
|
+
@logger.puts
|
22
|
+
@logger.wait cmd
|
23
|
+
exec(cmd)
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Options
|
28
|
+
#
|
29
|
+
|
30
|
+
options = {}
|
31
|
+
global_banner = <<DOC
|
32
|
+
|
33
|
+
Copy a file to the container
|
34
|
+
|
35
|
+
Usage: #{@cl_cmd_name} [options]
|
36
|
+
|
37
|
+
DOC
|
38
|
+
|
39
|
+
global = OptionParser.new do |g|
|
40
|
+
g.banner = global_banner
|
41
|
+
add_help_and_verbose(g)
|
42
|
+
|
43
|
+
g.on("-c", "--context CONTEXT", "a kubectl context name") do |v|
|
44
|
+
options[:kube_context] = v
|
45
|
+
end
|
46
|
+
|
47
|
+
g.on("-n", "--namespace NAMESPACE", "a kubectl namespace in the current context's cluster") do |v|
|
48
|
+
options[:namespace] = v
|
49
|
+
end
|
50
|
+
|
51
|
+
g.on("-d", "--deployment NAME", "a kubernetes deployment name") do |v|
|
52
|
+
options[:deployment_name] = v
|
53
|
+
end
|
54
|
+
|
55
|
+
g.on("-p", "--pod POD_NAME", "a kubernetes pod name") do |v|
|
56
|
+
options[:pod_name] = v
|
57
|
+
end
|
58
|
+
|
59
|
+
g.on("--container CONTAINER_NAME", "a kubernetes container you'd like to visit") do |v|
|
60
|
+
options[:container_name] = v
|
61
|
+
end
|
62
|
+
|
63
|
+
g.on("-l", "--local-filepath FILEPATH", "file you'd like to copy") do |v|
|
64
|
+
options[:local_filepath] = v
|
65
|
+
end
|
66
|
+
|
67
|
+
g.on("-r", "--remote-path PATH", "path to file you'd like to copy to") do |v|
|
68
|
+
options[:remote_path] = v
|
69
|
+
end
|
70
|
+
|
71
|
+
g.on("-x", "use magic tools context") do |v|
|
72
|
+
options[:ktx] = v
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Run
|
78
|
+
#
|
79
|
+
|
80
|
+
global.parse(ARGV)
|
81
|
+
|
82
|
+
# set pod and service
|
83
|
+
set_context_namespace_deployment_pod_container_options(options)
|
84
|
+
set_ktx(options)
|
85
|
+
|
86
|
+
# display full command
|
87
|
+
write_history("""#{@cl_cmd_name} \\
|
88
|
+
--context=#{options[:kube_context]} \\
|
89
|
+
--namespace=#{options[:namespace]} \\
|
90
|
+
--deployment=#{options[:deployment_name]} \\
|
91
|
+
--pod=#{options[:pod_name]} \\
|
92
|
+
--container=#{options[:container_name]} \\
|
93
|
+
--local-filepath=#{options[:local_filepath]} \\
|
94
|
+
--remote-path=#{options[:remote_path]}
|
95
|
+
""")
|
96
|
+
|
97
|
+
@working_dir = ENV['CL_WORKING_DIR']
|
98
|
+
|
99
|
+
upload_file(options)
|
@@ -0,0 +1,120 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/subcommand'
|
4
|
+
require 'tty-command'
|
5
|
+
require 'tty-prompt'
|
6
|
+
require 'json'
|
7
|
+
require 'pastel'
|
8
|
+
|
9
|
+
require 'cl/magic/common/common_options.rb'
|
10
|
+
require 'cl/magic/common/logging.rb'
|
11
|
+
require 'cl/magic/common/kubectl.rb'
|
12
|
+
|
13
|
+
@logger = get_logger()
|
14
|
+
@cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
|
15
|
+
|
16
|
+
#
|
17
|
+
# Features
|
18
|
+
#
|
19
|
+
|
20
|
+
def describe_selected_deployment(deployment, options)
|
21
|
+
@logger.puts ""
|
22
|
+
deployment_json = describe_deployment(options[:namespace], deployment)
|
23
|
+
git_project = deployment_json["metadata"]["annotations"]["git_project"]
|
24
|
+
git_commit = deployment_json["metadata"]["annotations"]["git_commit"]
|
25
|
+
|
26
|
+
pastel = Pastel.new
|
27
|
+
@logger.puts pastel.green("git_project:"), git_project
|
28
|
+
@logger.puts pastel.green("git_commit:"), git_commit
|
29
|
+
end
|
30
|
+
|
31
|
+
def describe_selected_pods(selected_pods, options)
|
32
|
+
pastel = Pastel.new
|
33
|
+
selected_pods.each do |selected_pod|
|
34
|
+
pod_name = selected_pod.first
|
35
|
+
@logger.puts ""
|
36
|
+
pod = describe_pod(options[:namespace], selected_pod)
|
37
|
+
host_ip = pod["status"]["hostIP"]
|
38
|
+
|
39
|
+
@logger.puts pastel.green("pod:"), pod_name, "(#{host_ip})"
|
40
|
+
pod["status"]["containerStatuses"].collect do |container|
|
41
|
+
image = container["image"]
|
42
|
+
image_parts = image.split(":").last.split('-')
|
43
|
+
@logger.puts pastel.green("image:"), image
|
44
|
+
|
45
|
+
if image_parts.count == 2
|
46
|
+
@logger.puts pastel.green("git_commit:"), image_parts.first
|
47
|
+
@logger.puts pastel.green("jenkins_build:"), image_parts.last
|
48
|
+
end
|
49
|
+
state = container["state"]
|
50
|
+
status = state.keys.first
|
51
|
+
started_at = state[status]['startedAt']
|
52
|
+
@logger.puts pastel.dim(status, " - ", started_at)
|
53
|
+
puts ""
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Options
|
61
|
+
#
|
62
|
+
|
63
|
+
options = {}
|
64
|
+
global_banner = <<DOC
|
65
|
+
|
66
|
+
Get build details on a deployment in google cloud
|
67
|
+
|
68
|
+
Usage: #{@cl_cmd_name} [filter-name] [options]
|
69
|
+
|
70
|
+
DOC
|
71
|
+
|
72
|
+
global = OptionParser.new do |g|
|
73
|
+
g.banner = global_banner
|
74
|
+
|
75
|
+
g.on("-c", "--context CONTEXT", "a kubectl context name") do |v|
|
76
|
+
options[:kube_context] = v
|
77
|
+
end
|
78
|
+
|
79
|
+
g.on("-n", "--namespace NAMESPACE", "a kubectl namespace in the current context's cluster") do |v|
|
80
|
+
options[:namespace] = v
|
81
|
+
end
|
82
|
+
|
83
|
+
g.on("-d", "--deployment NAME", "a kubernetes deployment name") do |v|
|
84
|
+
options[:deployment] = v
|
85
|
+
end
|
86
|
+
|
87
|
+
g.on("-p", "--pods PODS", "a csv of kubernetes pod names") do |v|
|
88
|
+
options[:pod_names] = v
|
89
|
+
end
|
90
|
+
|
91
|
+
g.on("-x", "use magic tools context") do |v|
|
92
|
+
options[:ktx] = v
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Run
|
98
|
+
#
|
99
|
+
|
100
|
+
global.parse(ARGV)
|
101
|
+
|
102
|
+
# set: context and namespace
|
103
|
+
set_context_and_namespace(options)
|
104
|
+
set_ktx(options)
|
105
|
+
|
106
|
+
# pick: deployment and pods
|
107
|
+
deployment = pick_kubectl_deployment(options)
|
108
|
+
pods = pick_kubectl_pods(deployment, options)
|
109
|
+
|
110
|
+
# display full command
|
111
|
+
write_history("""#{@cl_cmd_name} \\
|
112
|
+
--context=#{options[:kube_context]} \\
|
113
|
+
--namespace=#{options[:namespace]} \\
|
114
|
+
--deployment=#{deployment.first} \\
|
115
|
+
--pods=#{pods.collect(&:first).join(',')}
|
116
|
+
""")
|
117
|
+
|
118
|
+
# describe: deployment & pods
|
119
|
+
describe_selected_deployment(deployment, options)
|
120
|
+
describe_selected_pods(pods, options)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/subcommand'
|
4
|
+
require 'tty-command'
|
5
|
+
require 'tty-prompt'
|
6
|
+
require 'json'
|
7
|
+
require 'pastel'
|
8
|
+
|
9
|
+
require 'cl/magic/common/common_options.rb'
|
10
|
+
require 'cl/magic/common/logging.rb'
|
11
|
+
require 'cl/magic/common/kubectl.rb'
|
12
|
+
|
13
|
+
@logger = get_logger()
|
14
|
+
@cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
|
15
|
+
|
16
|
+
#
|
17
|
+
# Features
|
18
|
+
#
|
19
|
+
|
20
|
+
#
|
21
|
+
# Options
|
22
|
+
#
|
23
|
+
|
24
|
+
options = {}
|
25
|
+
global_banner = <<DOC
|
26
|
+
|
27
|
+
Set kube context
|
28
|
+
|
29
|
+
Usage: #{@cl_cmd_name} [filter-name] [options]
|
30
|
+
|
31
|
+
DOC
|
32
|
+
|
33
|
+
global = OptionParser.new do |g|
|
34
|
+
g.banner = global_banner
|
35
|
+
add_help_and_verbose(g)
|
36
|
+
|
37
|
+
g.on("-c", "--context CONTEXT", "a kubectl context name") do |v|
|
38
|
+
options[:kube_context] = v
|
39
|
+
end
|
40
|
+
|
41
|
+
g.on("-n", "--namespace NAMESPACE", "a kubectl namespace in the current context's cluster") do |v|
|
42
|
+
options[:namespace] = v
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Run
|
48
|
+
#
|
49
|
+
|
50
|
+
global.parse(ARGV)
|
51
|
+
|
52
|
+
# set: context and namespace
|
53
|
+
set_context_and_namespace(options)
|
54
|
+
set_ktx(options)
|
55
|
+
|
56
|
+
# display full command
|
57
|
+
write_history("""#{@cl_cmd_name} \\
|
58
|
+
--context=#{options[:kube_context]} \\
|
59
|
+
--namespace=#{options[:namespace]}
|
60
|
+
""")
|
@@ -0,0 +1,114 @@
|
|
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, pods, containers)
|
20
|
+
cmd = "kubectl stern '#{pods.collect(&:first).join('|')}' --context #{options[:kube_context]} --namespace #{options[:namespace]} --container '#{containers.collect(&:first).join('|')}' --since #{options[:since]} --container-state 'running,waiting,terminated'"
|
21
|
+
cmd += " | grep #{options[:grep]}" if options[:grep]
|
22
|
+
|
23
|
+
@logger.puts
|
24
|
+
@logger.wait cmd
|
25
|
+
exec(cmd) unless options[:dry_run]
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Options
|
30
|
+
#
|
31
|
+
|
32
|
+
options = { since: '60m'}
|
33
|
+
global_banner = <<DOC
|
34
|
+
|
35
|
+
A sandbox to try things
|
36
|
+
|
37
|
+
Usage: #{@cl_cmd_name} [options]
|
38
|
+
|
39
|
+
DOC
|
40
|
+
|
41
|
+
global = OptionParser.new do |g|
|
42
|
+
g.banner = global_banner
|
43
|
+
add_help_and_verbose(g)
|
44
|
+
|
45
|
+
g.on("-c", "--context CONTEXT", "a kubectl context name") do |v|
|
46
|
+
options[:kube_context] = v
|
47
|
+
end
|
48
|
+
|
49
|
+
g.on("-n", "--namespace NAMESPACE", "a kubectl namespace in the current context's cluster") do |v|
|
50
|
+
options[:namespace] = v
|
51
|
+
end
|
52
|
+
|
53
|
+
g.on("-d", "--deployment NAME", "a kubernetes deployment name") do |v|
|
54
|
+
options[:deployment] = v
|
55
|
+
end
|
56
|
+
|
57
|
+
g.on("--pick-pods", "let me select specific pods") do |v|
|
58
|
+
options[:pick_pods] = v
|
59
|
+
end
|
60
|
+
|
61
|
+
g.on("--grep PATTERN", "grep for a pattern and only show those logs") do |v|
|
62
|
+
options[:grep] = v
|
63
|
+
end
|
64
|
+
|
65
|
+
g.on("--dry-run", "only show me the command") do |v|
|
66
|
+
options[:dry_run] = v
|
67
|
+
end
|
68
|
+
|
69
|
+
g.on("--since TIME", "Return logs newer than a relative duration like 52, 2m, or 3h. Defaults to `1m`") do |v|
|
70
|
+
options[:since] = v
|
71
|
+
end
|
72
|
+
|
73
|
+
g.on("-x", "use magic tools context") do |v|
|
74
|
+
options[:ktx] = v
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Run
|
81
|
+
#
|
82
|
+
|
83
|
+
global.parse(ARGV)
|
84
|
+
|
85
|
+
# set: context and namespace
|
86
|
+
set_context_and_namespace(options)
|
87
|
+
set_ktx(options)
|
88
|
+
|
89
|
+
# pick: deployment and pods
|
90
|
+
deployment = pick_kubectl_deployment(options)
|
91
|
+
if options[:pick_pods]
|
92
|
+
pods = pick_kubectl_pods(deployment, options)
|
93
|
+
else
|
94
|
+
# all pods
|
95
|
+
selector = deployment.last # last field is a selector
|
96
|
+
pods = get_kubectl_pods(options[:namespace], selector).collect {|o| o.values_at(0,2)}
|
97
|
+
end
|
98
|
+
|
99
|
+
# pick: containers
|
100
|
+
uniq_containers = pods.collect do |pod|
|
101
|
+
get_containers_on_pod(options[:namespace], pod.first)
|
102
|
+
end.flatten(1).uniq
|
103
|
+
containers = pick_multiple_result(uniq_containers, "Pick containers", options[:container_names])
|
104
|
+
|
105
|
+
|
106
|
+
# display full command
|
107
|
+
write_history("""#{@cl_cmd_name} \\
|
108
|
+
--context=#{options[:kube_context]} \\
|
109
|
+
--namespace=#{options[:namespace]} \\
|
110
|
+
--deployment=#{deployment.first} \\
|
111
|
+
--grep=#{options[:grep]}
|
112
|
+
""")
|
113
|
+
|
114
|
+
do_work(options, pods, containers)
|