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,236 @@
|
|
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
|
+
# Kubectl config commands
|
9
|
+
#
|
10
|
+
|
11
|
+
def get_users_kube_config_cmd_path
|
12
|
+
tty_command = TTY::Command.new(printer: :null)
|
13
|
+
command = "grep cmd-path ~/.kube/config | head -n1 | cut -d ':' -f2"
|
14
|
+
out, err = tty_command.run(command)
|
15
|
+
return out.chomp.strip
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Kubectl DESCRIBE commands
|
20
|
+
#
|
21
|
+
|
22
|
+
def describe_pod(namespace, pod)
|
23
|
+
namespace_option = " --namespace=#{namespace}" if namespace
|
24
|
+
command = "kubectl get pod -ojson #{pod.first} #{namespace_option}"
|
25
|
+
@logger.wait command
|
26
|
+
result = TTY::Command.new(:printer => :null).run(command)
|
27
|
+
return JSON.parse(result.out)
|
28
|
+
end
|
29
|
+
|
30
|
+
def describe_deployment(namespace, deployment)
|
31
|
+
namespace_option = " --namespace=#{namespace}" if namespace
|
32
|
+
command = "kubectl get deployment.apps -ojson #{deployment.first} #{namespace_option}"
|
33
|
+
@logger.wait command
|
34
|
+
result = TTY::Command.new(:printer => :null).run(command)
|
35
|
+
return JSON.parse(result.out)
|
36
|
+
end
|
37
|
+
|
38
|
+
def describe_service(namespace, service)
|
39
|
+
namespace_option = " --namespace=#{namespace}" if namespace
|
40
|
+
command = "kubectl get service -ojson #{service.first} #{namespace_option}"
|
41
|
+
@logger.wait command
|
42
|
+
result = TTY::Command.new(:printer => :null).run(command)
|
43
|
+
return JSON.parse(result.out)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Kubectl GET commands
|
48
|
+
#
|
49
|
+
|
50
|
+
def get_kubectl_deployments(namespace)
|
51
|
+
namespace_option = namespace ? " --namespace=#{namespace}" : " --all-namespaces"
|
52
|
+
command = "kubectl get -o=wide deployment.apps #{namespace_option}"
|
53
|
+
error_message = "No deployments found"
|
54
|
+
return parse_table_results(command, error_message)
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_kubectl_pods(namespace, selector)
|
58
|
+
selector_option = " --selector=#{selector}" if selector
|
59
|
+
namespace_option = " --namespace=#{namespace}" if namespace
|
60
|
+
command = "kubectl get pods #{selector_option} #{namespace_option}"
|
61
|
+
error_message = "No pods found"
|
62
|
+
return parse_table_results(command, error_message)
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_kubectl_services(namespace)
|
66
|
+
namespace_option = " --namespace=#{namespace}" if namespace
|
67
|
+
command = "kubectl get -o=wide services #{namespace_option}"
|
68
|
+
error_message = "Your kubectl has no services; talk to your team about this. :)"
|
69
|
+
return parse_table_results(command, error_message)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_kubectl_namespaces()
|
73
|
+
command = "kubectl get namespaces"
|
74
|
+
error_message = "No namespaces found in kubectl context: #{get_current_kubectl_context()}"
|
75
|
+
return parse_table_results(command, error_message)
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_kubectl_contexts()
|
79
|
+
command = "kubectl config get-contexts"
|
80
|
+
error_message = "Your kubectl has no contexts; talk to your team about this. :)"
|
81
|
+
return parse_table_results(command, error_message)
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_current_kubectl_context()
|
85
|
+
command = "kubectl config current-context"
|
86
|
+
return TTY::Command.new(:printer => :null).run(command).out.strip.chomp
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_current_kubectl_namespace()
|
90
|
+
command = "kubectl config view --minify --output 'jsonpath={..namespace}'; echo"
|
91
|
+
return TTY::Command.new(:printer => :null).run(command).out.strip.chomp
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_containers_on_pod(namespace, pod_name)
|
95
|
+
command = "kubectl get pods #{pod_name} -o jsonpath='{.spec.containers[*].name}' --namespace #{namespace}"
|
96
|
+
return TTY::Command.new(:printer => :null).run(command).out.strip.chomp.split(' ').collect {|v|[v]}
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Kubectl pickers
|
101
|
+
#
|
102
|
+
|
103
|
+
def pick_kubectl_context(selected_context=nil)
|
104
|
+
|
105
|
+
prev_context = get_current_kubectl_context()
|
106
|
+
|
107
|
+
# pick content
|
108
|
+
if selected_context.nil?
|
109
|
+
selected_context = TTY::Prompt.new(interrupt: :exit).select("Which context?", filter: true, per_page: 20) do |menu|
|
110
|
+
get_kubectl_contexts().each do |context|
|
111
|
+
if context[0]=="*"
|
112
|
+
menu.default context[1]
|
113
|
+
menu.choice context[1], context[1]
|
114
|
+
else
|
115
|
+
menu.choice context[0], context[0]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# change context
|
122
|
+
if selected_context != prev_context
|
123
|
+
command = "kubectl config use-context #{selected_context}"
|
124
|
+
@logger.wait command
|
125
|
+
TTY::Command.new(:printer => :null).run(command)
|
126
|
+
end
|
127
|
+
|
128
|
+
return selected_context
|
129
|
+
end
|
130
|
+
|
131
|
+
def pick_kubectl_deployment(options)
|
132
|
+
deploments = get_kubectl_deployments(options[:namespace]).collect {|o| o.values_at(0,-1)}
|
133
|
+
deployment = pick_single_result(deploments, "Which deployment?", options[:deployment_name])
|
134
|
+
if deployment.nil? or deployment.last == '<none>'
|
135
|
+
@logger.error "No deployments found"
|
136
|
+
exit(1)
|
137
|
+
end
|
138
|
+
return deployment
|
139
|
+
end
|
140
|
+
|
141
|
+
def pick_kubectl_namespace(options)
|
142
|
+
namespaces = get_kubectl_namespaces().collect {|o| o.values_at(0)}
|
143
|
+
current_namespace = get_current_kubectl_namespace()
|
144
|
+
return pick_single_result(namespaces, "Which namespace?", options[:namespace], current_namespace)
|
145
|
+
end
|
146
|
+
|
147
|
+
def pick_kubectl_service(options)
|
148
|
+
services = get_kubectl_services(options[:namespace]).collect {|o| o.values_at(0,-1)}
|
149
|
+
service = pick_single_result(services, "Pick service", options[:service_name])
|
150
|
+
if service.nil? or service.last == '<none>'
|
151
|
+
@logger.error "No services found"
|
152
|
+
exit(1)
|
153
|
+
end
|
154
|
+
return service
|
155
|
+
end
|
156
|
+
|
157
|
+
def pick_kubectl_pods(deployment, options)
|
158
|
+
selector = deployment.last # last field is a selector
|
159
|
+
pods = get_kubectl_pods(options[:namespace], selector)
|
160
|
+
selected_pods = pick_multiple_result(pods, "Which pods?", options[:pod_names])
|
161
|
+
|
162
|
+
if selected_pods.count == 0
|
163
|
+
@logger.warn "deployment #{deployment.last} has no pods."
|
164
|
+
exit()
|
165
|
+
end
|
166
|
+
return selected_pods
|
167
|
+
end
|
168
|
+
|
169
|
+
def pick_kubectl_pod(service, options)
|
170
|
+
selector = service.last # last field is a selector
|
171
|
+
pods = get_kubectl_pods(options[:namespace], selector)
|
172
|
+
selected_pod = pick_single_result(pods, "Which pods?", options[:pod_name])
|
173
|
+
|
174
|
+
if selected_pod.nil?
|
175
|
+
@logger.error "service #{service.first} has no pod."
|
176
|
+
exit(1)
|
177
|
+
end
|
178
|
+
return selected_pod
|
179
|
+
end
|
180
|
+
|
181
|
+
def pick_kubectl_container(pod, options)
|
182
|
+
containers = get_containers_on_pod(options[:namespace], pod.first)
|
183
|
+
container = pick_single_result(containers, "Pick container", options[:container_name])
|
184
|
+
options[:container_name] = container.first
|
185
|
+
end
|
186
|
+
|
187
|
+
def set_context_namespace_deployment_pod_container_options(options)
|
188
|
+
# set: context and namespace
|
189
|
+
set_context_and_namespace(options)
|
190
|
+
|
191
|
+
# pick: deployment and pod
|
192
|
+
deployment = pick_kubectl_deployment(options)
|
193
|
+
pod = pick_kubectl_pod(deployment, options)
|
194
|
+
|
195
|
+
# set options
|
196
|
+
options[:deployment_name] = deployment.first
|
197
|
+
options[:pod_name] = pod.first
|
198
|
+
|
199
|
+
# set container
|
200
|
+
pick_kubectl_container(pod, options)
|
201
|
+
end
|
202
|
+
|
203
|
+
def set_context_and_namespace(options)
|
204
|
+
get_ktx(options) if options[:ktx]
|
205
|
+
|
206
|
+
# set: context and namespace
|
207
|
+
if options[:kube_context].nil? and options[:namespace].nil?
|
208
|
+
options[:kube_context] = pick_kubectl_context(options[:kube_context]) if options[:kube_context].nil?
|
209
|
+
options[:namespace] = pick_kubectl_namespace(options).first if options[:namespace].nil? # just the name
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
#
|
214
|
+
# cl ktx
|
215
|
+
#
|
216
|
+
KTX_FILEPATH = '.cl-ktx.json'
|
217
|
+
|
218
|
+
def set_ktx(options)
|
219
|
+
File.open(KTX_FILEPATH, "w") do |f|
|
220
|
+
f.write({
|
221
|
+
kube_context: options[:kube_context],
|
222
|
+
namespace: options[:namespace],
|
223
|
+
}.to_json)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def get_ktx(options)
|
228
|
+
if options[:ktx]
|
229
|
+
if(File.exist?(KTX_FILEPATH))
|
230
|
+
file = File.read(KTX_FILEPATH)
|
231
|
+
ktx_hash = JSON.parse(file)
|
232
|
+
options[:kube_context] = ktx_hash['kube_context']
|
233
|
+
options[:namespace] = ktx_hash['namespace']
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'tty-logger'
|
2
|
+
|
3
|
+
def get_logger
|
4
|
+
return TTY::Logger.new do |config|
|
5
|
+
config.types = {
|
6
|
+
puts: {level: :info},
|
7
|
+
}
|
8
|
+
config.handlers = [
|
9
|
+
[:console, {
|
10
|
+
styles: {
|
11
|
+
puts: {
|
12
|
+
symbol: "",
|
13
|
+
label: "",
|
14
|
+
color: :black,
|
15
|
+
levelpad: 0
|
16
|
+
},
|
17
|
+
}
|
18
|
+
}]
|
19
|
+
]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def write_history(message)
|
24
|
+
File.open("#{Dir.home}/.cl_history", "a") {|f| f.puts message }
|
25
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Parse table results
|
4
|
+
#
|
5
|
+
# Many commands return
|
6
|
+
# * a table of results
|
7
|
+
# * the first row being headers
|
8
|
+
# * each following row space separated values
|
9
|
+
#
|
10
|
+
# Lets assume this and parse the results
|
11
|
+
#
|
12
|
+
|
13
|
+
def parse_table_results(command, error_message, num_headers=1, split=nil, working_dir=nil)
|
14
|
+
results = []
|
15
|
+
|
16
|
+
@logger.puts ""
|
17
|
+
@logger.wait command
|
18
|
+
|
19
|
+
# working directory?
|
20
|
+
command = "cd #{working_dir} && #{command}" if working_dir
|
21
|
+
|
22
|
+
# run command
|
23
|
+
TTY::Command.new(:printer => :null).run(command).each { |line| results << line.split(split) }
|
24
|
+
num_headers.times { results.delete_at(0) } # remove header
|
25
|
+
|
26
|
+
if not results.any?
|
27
|
+
@logger.error error_message
|
28
|
+
exit(1)
|
29
|
+
end
|
30
|
+
return results
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
#
|
35
|
+
# Prompt the user to pick a single result
|
36
|
+
#
|
37
|
+
# results - and array of arrays
|
38
|
+
# prompt_message - the message for our picker
|
39
|
+
# exact - if provided, we'll return whatever matches this exactly
|
40
|
+
# default - if provided, the picker will default to this item
|
41
|
+
#
|
42
|
+
|
43
|
+
def pick_single_result(results, prompt_message, exact=nil, default=nil, selection_index=0)
|
44
|
+
|
45
|
+
# exact match?
|
46
|
+
results = results.select {|r| r[selection_index] == exact} if exact
|
47
|
+
|
48
|
+
case results.count
|
49
|
+
when 0 # no results?
|
50
|
+
return nil
|
51
|
+
when 1 # one result, just return it
|
52
|
+
return results.first
|
53
|
+
end
|
54
|
+
|
55
|
+
# prompt many results
|
56
|
+
selection = TTY::Prompt.new(interrupt: :exit).select(prompt_message, filter: true, per_page: 20) do |menu|
|
57
|
+
results.each do |result|
|
58
|
+
menu.default result.join(' | ') if result[selection_index] == default
|
59
|
+
menu.choice result.join(' | '), result[selection_index]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
return results.select { |r| r[selection_index]==selection }.first
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def pick_multiple_result(results, prompt_message, exacts=nil)
|
67
|
+
|
68
|
+
# exact match?
|
69
|
+
return results.select {|r| exacts.split(',').include? r.first} if exacts
|
70
|
+
|
71
|
+
# 0 or 1 result?
|
72
|
+
return results if results.count < 2
|
73
|
+
|
74
|
+
selections = TTY::Prompt.new(interrupt: :exit).multi_select(prompt_message, filter: true, per_page: 20) do |menu|
|
75
|
+
results.each do |result|
|
76
|
+
menu.choice result.join(' | '), result.first
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
return results.select {|r| selections.include? r.first}
|
81
|
+
end
|
data/lib/cl/magic.rb
ADDED
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cl-magic
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Don Najd
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-03-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: optparse-subcommand
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tty-logger
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tty-command
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: tty-prompt
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pastel
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: ''
|
112
|
+
email:
|
113
|
+
- dnajd7@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- Gemfile
|
119
|
+
- Gemfile.lock
|
120
|
+
- README.md
|
121
|
+
- bin/cl
|
122
|
+
- bin/console
|
123
|
+
- bin/setup
|
124
|
+
- cl-magic.gemspec
|
125
|
+
- lib/cl/magic.rb
|
126
|
+
- lib/cl/magic/cl
|
127
|
+
- lib/cl/magic/cl-auth
|
128
|
+
- lib/cl/magic/cl-aws-okta-auth
|
129
|
+
- lib/cl/magic/cl-aws-okta-env
|
130
|
+
- lib/cl/magic/cl-dk
|
131
|
+
- lib/cl/magic/cl-envkey
|
132
|
+
- lib/cl/magic/cl-gc-sql
|
133
|
+
- lib/cl/magic/cl-gc-tags
|
134
|
+
- lib/cl/magic/cl-glab-commit
|
135
|
+
- lib/cl/magic/cl-history
|
136
|
+
- lib/cl/magic/cl-kube-cp
|
137
|
+
- lib/cl/magic/cl-kube-deployment
|
138
|
+
- lib/cl/magic/cl-kube-ktx
|
139
|
+
- lib/cl/magic/cl-kube-logs
|
140
|
+
- lib/cl/magic/cl-kube-restart
|
141
|
+
- lib/cl/magic/cl-kube-search
|
142
|
+
- lib/cl/magic/cl-kube-search-all
|
143
|
+
- lib/cl/magic/cl-kube-ssh
|
144
|
+
- lib/cl/magic/cl-poll
|
145
|
+
- lib/cl/magic/cl-sandbox
|
146
|
+
- lib/cl/magic/cl-vault
|
147
|
+
- lib/cl/magic/common/common_options.rb
|
148
|
+
- lib/cl/magic/common/gcloud.rb
|
149
|
+
- lib/cl/magic/common/kubectl.rb
|
150
|
+
- lib/cl/magic/common/logging.rb
|
151
|
+
- lib/cl/magic/common/parse_and_pick.rb
|
152
|
+
- lib/cl/magic/version.rb
|
153
|
+
homepage: https://gitlab.com/beesbot/cl-magic
|
154
|
+
licenses:
|
155
|
+
- MIT
|
156
|
+
metadata:
|
157
|
+
allowed_push_host: https://rubygems.org/
|
158
|
+
homepage_uri: https://gitlab.com/beesbot/cl-magic
|
159
|
+
source_code_uri: https://gitlab.com/beesbot/cl-magic
|
160
|
+
changelog_uri: https://gitlab.com/beesbot/cl-magic
|
161
|
+
post_install_message:
|
162
|
+
rdoc_options: []
|
163
|
+
require_paths:
|
164
|
+
- lib
|
165
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: 2.6.0
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
175
|
+
requirements: []
|
176
|
+
rubygems_version: 3.1.6
|
177
|
+
signing_key:
|
178
|
+
specification_version: 4
|
179
|
+
summary: Magic tools for a turnkey developer experience
|
180
|
+
test_files: []
|