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.
@@ -0,0 +1,84 @@
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
+ if TTY::Prompt.new.yes?("Are you sure you want to restart #{options[:deployment]}?")
21
+ cmd = "kubectl rollout restart deployment/#{options[:deployment]} --namespace=#{options[:namespace]}"
22
+ @logger.puts
23
+ @logger.wait cmd
24
+ exec(cmd)
25
+ end
26
+ end
27
+
28
+ #
29
+ # Options
30
+ #
31
+
32
+ options = {}
33
+ global_banner = <<DOC
34
+
35
+ Restart a deployment for a service to refresh all the containers
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 DEPLOYMENT", "a kubectl deployment") do |v|
54
+ options[:deployment] = v
55
+ end
56
+
57
+ g.on("-x", "use magic tools context") do |v|
58
+ options[:ktx] = v
59
+ end
60
+
61
+ end
62
+
63
+ #
64
+ # Run
65
+ #
66
+
67
+ global.parse(ARGV)
68
+
69
+ # set: context and namespace
70
+ set_context_and_namespace(options)
71
+ set_ktx(options)
72
+
73
+ # set: deployment
74
+ options[:deployment] = pick_kubectl_deployment(options).first
75
+
76
+ # display full command
77
+ @logger.puts ""
78
+ write_history("""#{@cl_cmd_name} \\
79
+ --context=#{options[:kube_context]}
80
+ --namespace=#{options[:namespace]}
81
+ --deployment=#{options[:deployment]}
82
+ """)
83
+
84
+ do_work(options)
@@ -0,0 +1,111 @@
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/kubectl.rb'
9
+
10
+ @logger = get_logger()
11
+ @cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
12
+
13
+ #
14
+ # Features
15
+ #
16
+
17
+ def do_search(options)
18
+
19
+ # k8 api-resources
20
+ unless options[:kube_service_name]
21
+ @logger.puts ""
22
+ cmd = "kubectl api-resources --verbs=list --namespaced -o name | grep -v events.events.k8s.io | grep -v events | sort | uniq"
23
+ @logger.wait cmd
24
+ api_resources = TTY::Command.new(:printer => :null).run(cmd).collect { |line| line.split() }
25
+ options[:kube_service_name] = pick_single_result(api_resources, "Pick a resource").first
26
+ end
27
+
28
+ # display full command
29
+ write_history("""#{@cl_cmd_name} \\
30
+ --context=#{options[:kube_context]} \\
31
+ --service=#{options[:kube_service_name]} \\
32
+ --namespace=#{options[:namespace]}
33
+ """)
34
+
35
+ # get resources
36
+ @logger.puts ""
37
+ namespace = options[:namespace] ? "-n #{options[:namespace]}" : "--all-namespaces"
38
+ cmd = "kubectl get #{namespace} --ignore-not-found #{options[:kube_service_name]}"
39
+ cmd += " | grep #{options[:pattern]}" if options[:pattern]
40
+ @logger.wait cmd
41
+ result = TTY::Command.new(:printer => :null).run(cmd).out
42
+ only_one_result = options[:pattern] ? result.lines.count == 1 : result.lines.count == 2
43
+
44
+ # print resources
45
+ unless only_one_result
46
+ puts result
47
+ @logger.puts
48
+ end
49
+
50
+ # describe resource
51
+ if only_one_result or TTY::Prompt.new.yes?("Describe one of these resources?")
52
+ num_headers = options[:pattern] ? 0 : 1
53
+ resources_by_type = parse_table_results(cmd, "No resources found", num_headers=num_headers)
54
+ selection_index = 1
55
+ resource = pick_single_result(resources_by_type, "show resource?", nil, nil, selection_index)
56
+ cmd = "kubectl describe #{options[:kube_service_name]} #{resource[0]} --namespace=#{options[:namespace]}"
57
+ @logger.puts
58
+ @logger.wait cmd
59
+ puts TTY::Command.new(:printer => :null).run(cmd)
60
+ end
61
+ end
62
+
63
+ #
64
+ # Options
65
+ #
66
+
67
+ options = {}
68
+ global_banner = <<DOC
69
+
70
+ Search for k8 resources
71
+
72
+ Usage: #{@cl_cmd_name} [options]
73
+
74
+ DOC
75
+
76
+ global = OptionParser.new do |g|
77
+ g.banner = global_banner
78
+ add_help_and_verbose(g)
79
+
80
+ g.on("-c", "--context CONTEXT", "a kubectl context name") do |v|
81
+ options[:kube_context] = v
82
+ end
83
+
84
+ g.on("-s", "--service SERVICE_NAME", "a kubectl api-service name") do |v|
85
+ options[:kube_service_name] = v
86
+ end
87
+
88
+ g.on("-n", "--namespace NAMESPACE", "a kubectl namespace in the current context's cluster") do |v|
89
+ options[:namespace] = v
90
+ end
91
+
92
+ g.on("-p", "--pattern PATTERN", "pattern to grep for") do |v|
93
+ options[:pattern] = v
94
+ end
95
+
96
+ g.on("-x", "use magic tools context") do |v|
97
+ options[:ktx] = v
98
+ end
99
+ end
100
+
101
+ #
102
+ # Run
103
+ #
104
+
105
+ global.parse(ARGV)
106
+
107
+ # set: context
108
+ set_context_and_namespace(options) if options[:ktx]
109
+ options[:kube_context] = pick_kubectl_context(options[:kube_context])
110
+
111
+ do_search(options)
@@ -0,0 +1,97 @@
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 do_search(options)
21
+
22
+ # k8 api-resources
23
+ unless options[:kube_service_name]
24
+ @logger.puts ""
25
+ cmd = "kubectl api-resources --verbs=list --namespaced -o name | grep -v events.events.k8s.io | grep -v events | sort | uniq"
26
+ @logger.wait cmd
27
+ api_resources = TTY::Command.new(:printer => :null).run(cmd).collect { |line| line.split() }
28
+ options[:kube_service_name] = pick_single_result(api_resources, "Pick a resource").first
29
+ end
30
+
31
+ get_kubectl_contexts().each do |context|
32
+
33
+ context_name = context[1]
34
+
35
+ # set context
36
+ cmd = "kubectl config use-context #{context_name}"
37
+ TTY::Command.new(:printer => :null).run(cmd)
38
+
39
+ # searching in
40
+ puts "searching: #{context_name}"
41
+
42
+ # grep services
43
+ cmd = "kubectl get --all-namespaces --ignore-not-found #{options[:kube_service_name]}"
44
+ cmd += " | grep #{options[:pattern]}" if options[:pattern]
45
+
46
+ results = TTY::Command.new(:printer => :null).run!(cmd) do |out, err|
47
+ unless out.nil?
48
+ puts out
49
+ @logger.puts ""
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ #
57
+ # Options
58
+ #
59
+
60
+ options = {}
61
+ global_banner = <<DOC
62
+
63
+ Grep across all clusters and namespaces
64
+
65
+ Usage: #{@cl_cmd_name} [filter-name] [options]
66
+
67
+ DOC
68
+
69
+ global = OptionParser.new do |g|
70
+ g.banner = global_banner
71
+
72
+ g.on("-s", "--service SERVICE_NAME", "a kubectl api-service name; defaults to 'services'") do |v|
73
+ options[:kube_service_name] = v
74
+ end
75
+
76
+ g.on("-p", "--pattern PATTERN", "pattern to grep for") do |v|
77
+ options[:pattern] = v
78
+ end
79
+
80
+ g.on("-x", "use magic tools context") do |v|
81
+ options[:ktx] = v
82
+ end
83
+ end
84
+
85
+ #
86
+ # Run
87
+ #
88
+
89
+ global.parse(ARGV)
90
+
91
+ # display full command
92
+ write_history("""#{@cl_cmd_name} \\
93
+ --grep=#{options[:pattern]} \\
94
+ --service=#{options[:kube_service_name]}
95
+ """)
96
+
97
+ do_search(options)
@@ -0,0 +1,94 @@
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 visit_pod(options)
21
+ shell_command = options[:bash] ? "bash" : "sh"
22
+ cmd = "kubectl exec -it #{options[:pod_name]} --container #{options[:container_name]} --namespace #{options[:namespace]} -- #{shell_command}"
23
+ @logger.puts
24
+ @logger.wait cmd
25
+ exec(cmd)
26
+ end
27
+
28
+ #
29
+ # Options
30
+ #
31
+
32
+ options = {}
33
+ global_banner = <<DOC
34
+
35
+ Ssh into a container
36
+
37
+ Usage: #{@cl_cmd_name} [options]
38
+
39
+ DOC
40
+
41
+ global = OptionParser.new do |g|
42
+ g.banner = global_banner
43
+
44
+ g.on("-c", "--context CONTEXT", "a kubectl context name") do |v|
45
+ options[:kube_context] = v
46
+ end
47
+
48
+ g.on("-n", "--namespace NAMESPACE", "a kubectl namespace in the current context's cluster") do |v|
49
+ options[:namespace] = v
50
+ end
51
+
52
+ g.on("-d", "--deployment NAME", "a kubernetes deployment name") do |v|
53
+ options[:deployment_name] = v
54
+ end
55
+
56
+ g.on("-p", "--pod POD_NAME", "a kubernetes pod name") do |v|
57
+ options[:pod_name] = v
58
+ end
59
+
60
+ g.on("--container CONTAINER_NAME", "a kubernetes container you'd like to visit") do |v|
61
+ options[:container_name] = v
62
+ end
63
+
64
+ g.on("-x", "use magic tools context") do |v|
65
+ options[:ktx] = v
66
+ end
67
+
68
+ g.on("-b", "--bash", "bash instead of shell") do |v|
69
+ options[:bash] = v
70
+ end
71
+ end
72
+
73
+ #
74
+ # Run
75
+ #
76
+
77
+ global.parse(ARGV)
78
+
79
+ # set everything
80
+ set_context_namespace_deployment_pod_container_options(options)
81
+ set_ktx(options)
82
+
83
+ # display full command
84
+ write_history("""#{@cl_cmd_name} \\
85
+ --context=#{options[:kube_context]} \\
86
+ --namespace=#{options[:namespace]} \\
87
+ --deployment=#{options[:deployment_name]} \\
88
+ --pod=#{options[:pod_name]} \\
89
+ --container=#{options[:container_name]} \\
90
+ #{options[:bash] ? "--bash" : ""}
91
+ """)
92
+
93
+ # visit pod
94
+ visit_pod(options)
@@ -0,0 +1,51 @@
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
+ while true
21
+ tty_command = TTY::Command.new(printer: :null)
22
+ out, err = tty_command.run(ARGV.join(' '))
23
+ puts out
24
+ puts
25
+ sleep(1)
26
+ end
27
+ end
28
+
29
+ #
30
+ # Options
31
+ #
32
+
33
+ options = {}
34
+ global_banner = <<DOC
35
+
36
+ A sandbox to try things
37
+
38
+ Usage: #{@cl_cmd_name} [options]
39
+
40
+ DOC
41
+
42
+ global = OptionParser.new do |g|
43
+ g.banner = global_banner
44
+ add_help_and_verbose(g)
45
+ end
46
+
47
+ #
48
+ # Run
49
+ #
50
+
51
+ do_work(options)
@@ -0,0 +1,49 @@
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
+ write_history("""#{@cl_cmd_name}""")
21
+ @logger.success "Hello World"
22
+ end
23
+
24
+ #
25
+ # Options
26
+ #
27
+
28
+ options = {}
29
+ global_banner = <<DOC
30
+
31
+ A sandbox to try things
32
+
33
+ Usage: #{@cl_cmd_name} [options]
34
+
35
+ DOC
36
+
37
+ global = OptionParser.new do |g|
38
+ g.banner = global_banner
39
+ add_help_and_verbose(g)
40
+ end
41
+
42
+ #
43
+ # Run
44
+ #
45
+
46
+ @working_dir = ENV['CL_WORKING_DIR'] # passed through cl-magic to here
47
+ global.parse(ARGV)
48
+
49
+ do_work(options)
@@ -0,0 +1,84 @@
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 transverse_vault_path(path)
20
+
21
+ # list the folder
22
+ cmd = "vault list #{path}"
23
+ results = parse_table_results(cmd, "no secrets", num_headers=2)
24
+ selected_path = pick_single_result(results, "").first
25
+ new_path = File.join(path, selected_path)
26
+
27
+ if new_path.end_with? '/'
28
+ transverse_vault_path(new_path) # another folder, recurse
29
+ else
30
+ return new_path # picked a file
31
+ end
32
+ end
33
+
34
+ def print_secret(secret_path)
35
+
36
+ write_history("""#{@cl_cmd_name} \\
37
+ --secret=#{secret_path}
38
+ """)
39
+
40
+ cmd = "vault read #{secret_path}"
41
+ puts TTY::Command.new(:printer => :null).run(cmd).out
42
+ end
43
+
44
+ #
45
+ # Options
46
+ #
47
+
48
+ options = {}
49
+ global_banner = <<DOC
50
+
51
+ Browse secrets path and print a secret
52
+
53
+ Usage: #{@cl_cmd_name} [options]
54
+
55
+ DOC
56
+
57
+ global = OptionParser.new do |g|
58
+ g.banner = global_banner
59
+ add_help_and_verbose(g)
60
+
61
+ g.on("-p", "--path PATH", "a vault path to start from") do |v|
62
+ options[:vault_path] = v
63
+ end
64
+
65
+ g.on("-s", "--secret SECRET_PATH", "an exact secret to get") do |v|
66
+ options[:exact_secret_path] = v
67
+ end
68
+ end
69
+
70
+ #
71
+ # Run
72
+ #
73
+
74
+ global.parse(ARGV)
75
+
76
+ if options[:vault_path].nil?
77
+ options[:vault_path] = "secret"
78
+ end
79
+
80
+ if options[:exact_secret_path].nil?
81
+ options[:exact_secret_path] = transverse_vault_path(options[:vault_path])
82
+ end
83
+
84
+ print_secret(options[:exact_secret_path])
@@ -0,0 +1,16 @@
1
+
2
+ def add_help_and_verbose(opts)
3
+ add_verbose(opts)
4
+ add_help(opts)
5
+ end
6
+
7
+ def add_verbose(opts)
8
+ opts.on("-v", "--[no-]verbose")
9
+ end
10
+
11
+ def add_help(opts)
12
+ opts.on("-h", "--help") do
13
+ puts opts
14
+ exit
15
+ end
16
+ end
@@ -0,0 +1,71 @@
1
+ require 'json'
2
+ require 'tty-command'
3
+ require 'tty-prompt'
4
+ require 'cl/magic/common/logging.rb'
5
+ require 'cl/magic/common/parse_and_pick.rb'
6
+
7
+ #
8
+ # gcloud GET
9
+ #
10
+
11
+ def get_gcloud_projects(filter=nil)
12
+ filter_option = "--filter #{filter}" if filter
13
+ command = "gcloud projects list #{filter_option}"
14
+ error_message = "No gcloud projects? Are you authenticated?"
15
+ return parse_table_results(command, error_message)
16
+ end
17
+
18
+ def get_current_gcloud_project()
19
+ command = "gcloud config get-value project"
20
+ return TTY::Command.new(:printer => :null).run(command).out.strip.chomp
21
+ end
22
+
23
+ def get_sql_instances()
24
+ command = "gcloud sql instances list"
25
+ return parse_table_results(command, 'No sql instances. :(')
26
+ end
27
+
28
+ def get_sql_users(instance)
29
+ command = "gcloud sql users list --instance=#{instance.first}"
30
+ return parse_table_results(command, 'No sql users. :(')
31
+ end
32
+
33
+ def get_sql_databases(instance)
34
+ command = "gcloud sql databases list --instance=#{instance.first}"
35
+ return parse_table_results(command, 'No sql databases. :(')
36
+ end
37
+
38
+ #
39
+ # Misc
40
+ #
41
+
42
+ def pick_gcloud_project(filter=nil)
43
+
44
+ prev_project = get_current_gcloud_project()
45
+
46
+ # pick content
47
+ projects = get_gcloud_projects(filter)
48
+ selected_project = pick_single_result(projects, 'Pick a project', nil, prev_project)
49
+
50
+ # change context
51
+ if selected_project.first != prev_project
52
+ command = "gcloud config set project #{selected_project.first}"
53
+ @logger.wait command
54
+ TTY::Command.new(:printer => :null).run(command)
55
+ else
56
+ @logger.info "project already set to #{selected_project.first}"
57
+ end
58
+
59
+ return selected_project
60
+ end
61
+
62
+ def check_gcloud_project(project)
63
+ command = "gcloud info"
64
+ result = TTY::Command.new(:printer => :null).run(command)
65
+
66
+ current_project = result.select {|line| line.include? 'Project'}.first.split(': ').last
67
+ if current_project != "[#{current_project}]"
68
+ @logger.warn "Incorrect gcloud project: #{current_project}"
69
+ @logger.warn "Use `gcloud config set project #{project}` and try again."
70
+ end
71
+ end