kubernetes-cli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bb7820fe8fd6c5426e502bfaeab2e5e7b3ae3350900ffdab42acaa3328bd0fd7
4
+ data.tar.gz: ce6976bd46b6a7f98438738fc53910fef7ecce53082bb06062be49833892912c
5
+ SHA512:
6
+ metadata.gz: 53d1088eb10bdcaa0373d595fcc8dede6495f16836a2a985957082f8f33a99f2e1ae8892001eb8c15d0327a02c75e75e6ca71b3cf9d57cd7d5cdd5b2e6396199
7
+ data.tar.gz: 80b1971145ced2eb828df6cf61c63b909faa6a55650c745eaa1725b229e82f355ad1b7128834f38f1f3e6fe0a1205c917ab68ce9aa147f17674582aac209c724
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ * Birthday!
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # Declare platform-specific gems here so they install correctly.
6
+ # See: https://github.com/rubygems/rubygems/issues/3646
7
+ gem 'kubectl-rb'
8
+
9
+ group :development do
10
+ gem 'rake'
11
+ end
12
+
13
+ group :test do
14
+ gem 'rspec'
15
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Cameron Dutro
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubygems/package_task'
4
+
5
+ require 'kubernetes-cli'
6
+
7
+ Bundler::GemHelper.install_tasks
8
+
9
+ task default: :spec
10
+
11
+ desc 'Run specs'
12
+ RSpec::Core::RakeTask.new do |t|
13
+ t.pattern = './spec/**/*_spec.rb'
14
+ end
@@ -0,0 +1,18 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ require 'kubernetes-cli/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'kubernetes-cli'
6
+ s.version = ::KubernetesCLI::VERSION
7
+ s.authors = ['Cameron Dutro']
8
+ s.email = ['camertron@gmail.com']
9
+ s.homepage = 'http://github.com/getkuby/kubernetes-cli'
10
+ s.license = 'MIT'
11
+
12
+ s.description = s.summary = 'Ruby wrapper around the Kubernetes CLI.'
13
+
14
+ s.add_dependency 'kubectl-rb', '~> 0.1'
15
+
16
+ s.require_path = 'lib'
17
+ s.files = Dir['{lib,spec,vendor}/**/*', 'Gemfile', 'LICENSE', 'CHANGELOG.md', 'README.md', 'Rakefile', 'kubernetes-cli.gemspec']
18
+ end
@@ -0,0 +1,217 @@
1
+ require 'kubectl-rb'
2
+
3
+ class KubernetesCLI
4
+ attr_reader :kubeconfig_path, :executable
5
+
6
+ def initialize(kubeconfig_path, executable = KubectlRb.executable)
7
+ @kubeconfig_path = kubeconfig_path
8
+ @executable = executable
9
+ @before_execute = []
10
+ @after_execute = []
11
+ end
12
+
13
+ def before_execute(&block)
14
+ @before_execute << block
15
+ end
16
+
17
+ def after_execute(&block)
18
+ @after_execute << block
19
+ end
20
+
21
+ def last_status
22
+ Thread.current[status_key]
23
+ end
24
+
25
+ def run_cmd(cmd)
26
+ cmd = [executable, '--kubeconfig', kubeconfig_path, *Array(cmd)]
27
+ execc(cmd)
28
+ end
29
+
30
+ def exec_cmd(container_cmd, namespace, pod, tty = true)
31
+ cmd = [executable, '--kubeconfig', kubeconfig_path, '-n', namespace, 'exec']
32
+ cmd += ['-it'] if tty
33
+ cmd += [pod, '--', *Array(container_cmd)]
34
+ execc(cmd)
35
+ end
36
+
37
+ def apply(res, dry_run: false)
38
+ cmd = [executable, '--kubeconfig', kubeconfig_path, 'apply', '--validate']
39
+ cmd << '--dry-run=client' if dry_run
40
+ cmd += ['-f', '-']
41
+
42
+ open3_w(env, cmd) do |stdin, _wait_thread|
43
+ stdin.puts(res.to_resource.to_yaml)
44
+ end
45
+
46
+ unless last_status.success?
47
+ err = InvalidResourceError.new("Could not apply #{res.kind_sym.to_s.humanize.downcase} "\
48
+ "'#{res.metadata.name}': kubectl exited with status code #{last_status.exitstatus}"
49
+ )
50
+
51
+ err.resource = res
52
+ raise err
53
+ end
54
+ end
55
+
56
+ def apply_uri(uri, dry_run: false)
57
+ cmd = [executable, '--kubeconfig', kubeconfig_path, 'apply', '--validate']
58
+ cmd << '--dry-run=client' if dry_run
59
+ cmd += ['-f', uri]
60
+ systemm(cmd)
61
+
62
+ unless last_status.success?
63
+ err = InvalidResourceUriError.new("Could not apply #{uri}: "\
64
+ "kubectl exited with status code #{last_status.exitstatus}"
65
+ )
66
+
67
+ err.resource_uri = uri
68
+ raise err
69
+ end
70
+ end
71
+
72
+ def get_object(type, namespace, name = nil, match_labels = {})
73
+ cmd = [executable, '--kubeconfig', kubeconfig_path, '-n', namespace]
74
+ cmd += ['get', type, name]
75
+
76
+ unless match_labels.empty?
77
+ cmd += ['--selector', match_labels.map { |key, value| "#{key}=#{value}" }.join(',')]
78
+ end
79
+
80
+ cmd += ['-o', 'json']
81
+
82
+ result = backticks(cmd)
83
+
84
+ unless last_status.success?
85
+ raise GetResourceError, "couldn't get resources of type '#{type}' "\
86
+ "in namespace #{namespace}: kubectl exited with status code #{last_status.exitstatus}"
87
+ end
88
+
89
+ JSON.parse(result)
90
+ end
91
+
92
+ def get_objects(type, namespace, match_labels = {})
93
+ cmd = [executable, '--kubeconfig', kubeconfig_path, '-n', namespace]
94
+ cmd += ['get', type]
95
+
96
+ unless match_labels.empty?
97
+ cmd += ['--selector', match_labels.map { |key, value| "#{key}=#{value}" }.join(',')]
98
+ end
99
+
100
+ cmd += ['-o', 'json']
101
+
102
+ result = backticks(cmd)
103
+
104
+ unless last_status.success?
105
+ raise GetResourceError, "couldn't get resources of type '#{type}' "\
106
+ "in namespace #{namespace}: kubectl exited with status code #{last_status.exitstatus}"
107
+ end
108
+
109
+ JSON.parse(result)['items']
110
+ end
111
+
112
+ def annotate(type, namespace, name, annotations, overwrite: true)
113
+ cmd = [
114
+ executable,
115
+ '--kubeconfig', kubeconfig_path,
116
+ '-n', namespace,
117
+ 'annotate'
118
+ ]
119
+
120
+ cmd << '--overwrite' if overwrite
121
+ cmd += [type, name]
122
+
123
+ annotations.each do |key, value|
124
+ cmd << "'#{key}'='#{value}'"
125
+ end
126
+
127
+ systemm(cmd)
128
+
129
+ unless last_status.success?
130
+ raise KubernetesCLIError, "could not annotate resource '#{name}': kubectl "\
131
+ "exited with status code #{last_status.exitstatus}"
132
+ end
133
+ end
134
+
135
+ def logtail(namespace, selector, follow: true)
136
+ cmd = [executable, '--kubeconfig', kubeconfig_path, '-n', namespace, 'logs']
137
+ cmd << '-f' if follow
138
+ cmd << '--selector'
139
+ cmd << selector.map { |k, v| "#{k}=#{v}" }.join(',')
140
+ execc(cmd)
141
+ end
142
+
143
+ def current_context
144
+ cmd = [executable, '--kubeconfig', kubeconfig_path, 'config', 'current-context']
145
+ backticks(cmd).strip
146
+ end
147
+
148
+ private
149
+
150
+ def env
151
+ @env ||= {}
152
+ end
153
+
154
+ def status_key
155
+ :kubernetes_cli_last_status
156
+ end
157
+
158
+ def base_cmd
159
+ [executable, '--kubeconfig', kubeconfig_path]
160
+ end
161
+
162
+ def backticks(cmd)
163
+ cmd_s = cmd.join(' ')
164
+ `#{cmd_s}`.tap do
165
+ self.last_status = $?
166
+ end
167
+ end
168
+
169
+ def execc(cmd)
170
+ run_before_callbacks(cmd)
171
+ cmd_s = cmd.join(' ')
172
+ exec(cmd_s)
173
+ end
174
+
175
+ def systemm(cmd)
176
+ run_before_callbacks(cmd)
177
+ cmd_s = cmd.join(' ')
178
+ system(cmd_s).tap do
179
+ self.last_status = $?
180
+ run_after_callbacks(cmd)
181
+ end
182
+ end
183
+
184
+ def backticks(cmd)
185
+ run_before_callbacks(cmd)
186
+ cmd_s = cmd.join(' ')
187
+ `#{cmd_s}`.tap do
188
+ self.last_status = $?
189
+ run_after_callbacks(cmd)
190
+ end
191
+ end
192
+
193
+ def open3_w(env, cmd, opts = {}, &block)
194
+ run_before_callbacks(cmd)
195
+ cmd_s = cmd.join(' ')
196
+
197
+ Open3.pipeline_w([env, cmd_s], opts) do |stdin, wait_threads|
198
+ yield(stdin, wait_threads).tap do
199
+ stdin.close
200
+ self.last_status = wait_threads.last.value
201
+ run_after_callbacks(cmd)
202
+ end
203
+ end
204
+ end
205
+
206
+ def run_before_callbacks(cmd)
207
+ @before_execute.each { |cb| cb.call(cmd) }
208
+ end
209
+
210
+ def run_after_callbacks(cmd)
211
+ @after_execute.each { |cb| cb.call(cmd, last_status) }
212
+ end
213
+
214
+ def last_status=(status)
215
+ Thread.current[status_key] = status
216
+ end
217
+ end
@@ -0,0 +1,3 @@
1
+ class KubernetesCLI
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kubernetes-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Cameron Dutro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kubectl-rb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.1'
27
+ description: Ruby wrapper around the Kubernetes CLI.
28
+ email:
29
+ - camertron@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - CHANGELOG.md
35
+ - Gemfile
36
+ - LICENSE
37
+ - Rakefile
38
+ - kubernetes-cli.gemspec
39
+ - lib/kubernetes-cli.rb
40
+ - lib/kubernetes-cli/version.rb
41
+ homepage: http://github.com/getkuby/kubernetes-cli
42
+ licenses:
43
+ - MIT
44
+ metadata: {}
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubygems_version: 3.0.6
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: Ruby wrapper around the Kubernetes CLI.
64
+ test_files: []