Class: KubernetesCLI

Inherits:
Object
  • Object
show all
Defined in:
lib/kubernetes-cli/version.rb,
lib/kubernetes-cli.rb
more...

Overview

typed: ignore

Defined Under Namespace

Classes: AnnotateResourceError, DeleteResourceError, GetResourceError, GetVersionError, InvalidResourceError, InvalidResourceUriError, KubernetesError, PatchResourceError

Constant Summary collapse

STATUS_KEY =
:kubernetes_cli_last_status
STDOUT_KEY =
:kubernetes_cli_stdout
STDERR_KEY =
:kubernetes_cli_stderr
VERSION =
'0.6.0'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(kubeconfig_path, executable = KubectlRb.executable) ⇒ KubernetesCLI

T::Sig::WithoutRuntime.sig { params(kubeconfig_path: String, executable: String).void }

[View source]

68
69
70
71
72
73
74
# File 'lib/kubernetes-cli.rb', line 68

def initialize(kubeconfig_path, executable = KubectlRb.executable)
  @kubeconfig_path = kubeconfig_path
  @executable = executable
  @before_execute = []
  @after_execute = []
  # @env = T.let(@env, T.nilable(T::Hash[String, String]))
end

Instance Attribute Details

#executableObject (readonly)

T::Sig::WithoutRuntime.sig { returns(String) }


60
61
62
# File 'lib/kubernetes-cli.rb', line 60

def executable
  @executable
end

#kubeconfig_pathObject (readonly)

T::Sig::WithoutRuntime.sig { returns(String) }


57
58
59
# File 'lib/kubernetes-cli.rb', line 57

def kubeconfig_path
  @kubeconfig_path
end

Instance Method Details

#after_execute(&block) ⇒ Object

T::Sig::WithoutRuntime.sig { params(block: AfterCallback).void }

[View source]

82
83
84
# File 'lib/kubernetes-cli.rb', line 82

def after_execute(&block)
  @after_execute << block
end

#annotate(type, namespace, name, annotations, overwrite: true) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  type: String,
  namespace: String,
  name: String,
  annotations: T::Hash[String, String],
  overwrite: T::Boolean
).void

[View source]

349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/kubernetes-cli.rb', line 349

def annotate(type, namespace, name, annotations, overwrite: true)
  cmd = [
    executable,
    '--kubeconfig', kubeconfig_path,
    '-n', namespace,
    'annotate'
  ]

  cmd << '--overwrite' if overwrite
  cmd += [type, name]

  annotations.each do |key, value|
    cmd << "'#{key}'='#{value}'"
  end

  systemm(cmd)

  on_last_status_failure do |last_status|
    raise AnnotateResourceError, "could not annotate resource '#{name}': kubectl "\
      "exited with status code #{last_status.exitstatus}"
  end
end

#api_resourcesObject

T::Sig::WithoutRuntime.sig { returns(String) }

[View source]

394
395
396
397
398
399
400
401
402
403
404
# File 'lib/kubernetes-cli.rb', line 394

def api_resources
  cmd = [executable, '--kubeconfig', kubeconfig_path, 'api-resources']
  result = backticks(cmd)

  on_last_status_failure do |last_status|
    raise KubernetesError, 'could not fetch API resources: kubectl exited with '\
      "status code #{last_status.exitstatus}. #{result}"
  end

  result
end

#apply(res, dry_run: false) ⇒ Object

T::Sig::WithoutRuntime.sig { params(res: ::KubeDSL::DSLObject, dry_run: T::Boolean).void }

[View source]

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/kubernetes-cli.rb', line 163

def apply(res, dry_run: false)
  cmd = [executable, '--kubeconfig', kubeconfig_path, 'apply', '--validate']
  cmd << '--dry-run=client' if dry_run
  cmd += ['-f', '-']

  open3_w(env, cmd) do |stdin|
    stdin.puts(res.to_resource.to_yaml)
  end

  on_last_status_failure do |last_status|
    err = InvalidResourceError.new("Could not apply #{res.kind_sym} "\
      "'#{res..name}': kubectl exited with status code #{last_status.exitstatus}"
    )

    err.resource = res
    raise err
  end
end

#apply_uri(uri, dry_run: false) ⇒ Object

T::Sig::WithoutRuntime.sig { params(uri: String, dry_run: T::Boolean).void }

[View source]

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/kubernetes-cli.rb', line 183

def apply_uri(uri, dry_run: false)
  cmd = [executable, '--kubeconfig', kubeconfig_path, 'apply', '--validate']
  cmd << '--dry-run=client' if dry_run
  cmd += ['-f', uri]
  systemm(cmd)

  on_last_status_failure do |last_status|
    err = InvalidResourceUriError.new("Could not apply #{uri}: "\
      "kubectl exited with status code #{last_status.exitstatus}"
    )

    err.resource_uri = uri
    raise err
  end
end

#before_execute(&block) ⇒ Object

T::Sig::WithoutRuntime.sig { params(block: BeforeCallback).void }

[View source]

77
78
79
# File 'lib/kubernetes-cli.rb', line 77

def before_execute(&block)
  @before_execute << block
end

#current_contextObject

T::Sig::WithoutRuntime.sig { returns(String) }

[View source]

388
389
390
391
# File 'lib/kubernetes-cli.rb', line 388

def current_context
  cmd = [executable, '--kubeconfig', kubeconfig_path, 'config', 'current-context']
  backticks(cmd).strip
end

#delete_object(type, namespace, name) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  type: String,
  namespace: String,
  name: String
).void

[View source]

273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/kubernetes-cli.rb', line 273

def delete_object(type, namespace, name)
  cmd = [executable, '--kubeconfig', kubeconfig_path]
  cmd += ['-n', namespace] if namespace
  cmd += ['delete', type, name]

  systemm(cmd)

  on_last_status_failure do |last_status|
    raise DeleteResourceError, "couldn't delete resource of type '#{type}' named '#{name}' "\
      "in namespace #{namespace}: kubectl exited with status code #{last_status.exitstatus}"
  end
end

#delete_objects(type, namespace, match_labels = {}) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  type: String,
  namespace: T.any(String, Symbol),
  match_labels: T::Hash[String, String]
).void

[View source]

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/kubernetes-cli.rb', line 293

def delete_objects(type, namespace, match_labels = {})
  cmd = [executable, '--kubeconfig', kubeconfig_path]

  if namespace == :all
    cmd << '--all-namespaces'
  elsif namespace
    cmd += ['-n', namespace.to_s]
  end

  cmd += ['delete', type]

  unless match_labels.empty?
    cmd += ['--selector', match_labels.map { |key, value| "#{key}=#{value}" }.join(',')]
  end

  systemm(cmd)

  on_last_status_failure do |last_status|
    raise DeleteResourceError, "couldn't delete resources of type '#{type}' "\
      "in namespace #{namespace}: kubectl exited with status code #{last_status.exitstatus}"
  end
end

#envObject

T::Sig::WithoutRuntime.sig { returns(T::Hash[String, String]) }

[View source]

456
457
458
# File 'lib/kubernetes-cli.rb', line 456

def env
  @env ||= {}
end

#exec_cmd(container_cmd, namespace, pod, tty = true, container = nil, out_file = nil) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  container_cmd: T.any(String, T::Array[String]),
  namespace: String,
  pod: String,
  tty: T::Boolean,
  container: T.nilable(String),
  out_file: T.nilable(String)
).void

[View source]

136
137
138
139
140
141
142
143
# File 'lib/kubernetes-cli.rb', line 136

def exec_cmd(container_cmd, namespace, pod, tty = true, container = nil, out_file = nil)
  cmd = [executable, '--kubeconfig', kubeconfig_path, '-n', namespace, 'exec']
  cmd += ['-it'] if tty
  cmd += ['-c', container] if container
  cmd += [pod, '--', *Array(container_cmd)]
  cmd += ['>', out_file] if out_file
  execc(cmd)
end

#get_object(type, namespace, name) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  type: String,
  namespace: String,
  name: String
).returns(
  T::Hash[String, T.untyped]
)

[View source]

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/kubernetes-cli.rb', line 208

def get_object(type, namespace, name)
  cmd = [executable, '--kubeconfig', kubeconfig_path]
  cmd += ['-n', namespace] if namespace
  cmd += ['get', type, name]
  cmd += ['-o', 'json']

  result = backticks(cmd)

  on_last_status_failure do |last_status|
    raise GetResourceError, "couldn't get resource of type '#{type}' named '#{name}' "\
      "in namespace #{namespace}: kubectl exited with status code #{last_status.exitstatus}"
  end

  begin
    JSON.parse(result)
  rescue JSON::ParserError
    raise GetResourceError, "json parsing error"
  end
end

#get_objects(type, namespace, match_labels = {}) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  type: String,
  namespace: T.any(String, Symbol),
  match_labels: T::Hash[String, String]
).returns(
  T::Array[T.untyped]
)

[View source]

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/kubernetes-cli.rb', line 237

def get_objects(type, namespace, match_labels = {})
  cmd = [executable, '--kubeconfig', kubeconfig_path, 'get', type]

  if namespace == :all
    cmd << '--all-namespaces'
  elsif namespace
    cmd += ['-n', namespace.to_s]
  end

  unless match_labels.empty?
    cmd += ['--selector', match_labels.map { |key, value| "#{key}=#{value}" }.join(',')]
  end

  cmd += ['-o', 'json']

  result = backticks(cmd)

  on_last_status_failure do |last_status|
    raise GetResourceError, "couldn't get resources of type '#{type}' "\
      "in namespace #{namespace}: kubectl exited with status code #{last_status.exitstatus}"
  end

  begin
    JSON.parse(result)['items']
  rescue JSON::ParserError
    raise GetResourceError, "json parsing error"
  end
end

#last_statusObject

T::Sig::WithoutRuntime.sig { returns(T.nilable(Process::Status)) }

[View source]

87
88
89
# File 'lib/kubernetes-cli.rb', line 87

def last_status
  Thread.current[STATUS_KEY]
end

#logtail(namespace, selector, follow: true) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  namespace: String,
  selector: T::Hash[String, String],
  follow: T::Boolean
).void

[View source]

379
380
381
382
383
384
385
# File 'lib/kubernetes-cli.rb', line 379

def logtail(namespace, selector, follow: true)
  cmd = [executable, '--kubeconfig', kubeconfig_path, '-n', namespace, 'logs']
  cmd << '-f' if follow
  cmd << '--selector'
  cmd << selector.map { |k, v| "#{k}=#{v}" }.join(',')
  execc(cmd)
end

#on_last_status_failure(&block) ⇒ Object

T::Sig::WithoutRuntime.sig { params(block: T.proc.params(last_status: Process::Status).void).void }

[View source]

97
98
99
100
101
# File 'lib/kubernetes-cli.rb', line 97

def on_last_status_failure(&block)
  with_last_status do |ls|
    block.call(ls) unless ls.success?
  end
end

#patch_object(type, namespace, name, patch_data, patch_type = 'merge') ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  type: String,
  namespace: String,
  name: String,
  patch_data: String,
  patch_type: String
).void

[View source]

325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/kubernetes-cli.rb', line 325

def patch_object(type, namespace, name, patch_data, patch_type = 'merge')
  cmd = [executable, '--kubeconfig', kubeconfig_path]
  cmd += ['-n', namespace] if namespace
  cmd += ['patch', type, name]
  cmd += ['-p', Shellwords.shellescape(patch_data)]
  cmd += ['--type', patch_type]

  systemm(cmd)

  on_last_status_failure do |last_status|
    raise PatchResourceError, "couldn't patch resource of type '#{type}' named '#{name}' "\
      "in namespace #{namespace}: kubectl exited with status code #{last_status.exitstatus}"
  end
end

#restart_deployment(namespace, deployment) ⇒ Object

T::Sig::WithoutRuntime.sig { params(namespace: String, deployment: String).void }

[View source]

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/kubernetes-cli.rb', line 407

def restart_deployment(namespace, deployment)
  cmd = [
    executable,
    '--kubeconfig', kubeconfig_path,
    '-n', namespace,
    'rollout', 'restart', 'deployment', deployment
  ]

  systemm(cmd)

  on_last_status_failure do |last_status|
    raise KubernetesError, 'could not restart deployment: kubectl exited with '\
      "status code #{last_status.exitstatus}"
  end
end

#run_cmd(cmd) ⇒ Object

T::Sig::WithoutRuntime.sig { params(cmd: T.any(String, T::Array)).void }

[View source]

121
122
123
124
# File 'lib/kubernetes-cli.rb', line 121

def run_cmd(cmd)
  cmd = [executable, '--kubeconfig', kubeconfig_path, *Array(cmd)]
  execc(cmd)
end

#stderrObject

T::Sig::WithoutRuntime.sig { returns(T.any(StringIO, IO)) }

[View source]

446
447
448
# File 'lib/kubernetes-cli.rb', line 446

def stderr
  Thread.current[STDERR_KEY] || STDERR
end

#stderr=(new_stderr) ⇒ Object

T::Sig::WithoutRuntime.sig { params(new_stderr: T.nilable(T.any(StringIO, IO))).void }

[View source]

451
452
453
# File 'lib/kubernetes-cli.rb', line 451

def stderr=(new_stderr)
  Thread.current[STDERR_KEY] = new_stderr
end

#stdoutObject

T::Sig::WithoutRuntime.sig { returns(T.any(StringIO, IO)) }

[View source]

436
437
438
# File 'lib/kubernetes-cli.rb', line 436

def stdout
  Thread.current[STDOUT_KEY] || STDOUT
end

#stdout=(new_stdout) ⇒ Object

T::Sig::WithoutRuntime.sig { params(new_stdout: T.nilable(T.any(StringIO, IO))).void }

[View source]

441
442
443
# File 'lib/kubernetes-cli.rb', line 441

def stdout=(new_stdout)
  Thread.current[STDOUT_KEY] = new_stdout
end

#system_cmd(container_cmd, namespace, pod, tty = true, container = nil) ⇒ Object

T::Sig::WithoutRuntime.sig

params(
  container_cmd: T.any(String, T::Array[String]),
  namespace: String,
  pod: String,
  tty: T::Boolean,
  container: T.nilable(String)
).void

[View source]

154
155
156
157
158
159
160
# File 'lib/kubernetes-cli.rb', line 154

def system_cmd(container_cmd, namespace, pod, tty = true, container = nil)
  cmd = [executable, '--kubeconfig', kubeconfig_path, '-n', namespace, 'exec']
  cmd += ['-it'] if tty
  cmd += ['-c', container] if container
  cmd += [pod, '--', *Array(container_cmd)]
  systemm(cmd)
end

#versionObject

T::Sig::WithoutRuntime.sig { returns(T::Hash[T.untyped, T.untyped]) }

[View source]

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/kubernetes-cli.rb', line 104

def version
  cmd = [executable, '--kubeconfig', kubeconfig_path, 'version', '-o', 'json']
  result = backticks(cmd)

  on_last_status_failure do |last_status|
    raise GetVersionError, "couldn't get version info: "\
      "kubectl exited with status code #{last_status.exitstatus}"
  end

  begin
    JSON.parse(result)
  rescue JSON::ParserError
    raise GetVersionError, "json parsing error"
  end
end

#with_last_status(&block) ⇒ Object

T::Sig::WithoutRuntime.sig { params(block: T.proc.params(last_status: Process::Status).void).void }

[View source]

92
93
94
# File 'lib/kubernetes-cli.rb', line 92

def with_last_status(&block)
  block.call(last_status)
end

#with_pipes(out = STDOUT, err = STDERR, &block) ⇒ Object

T::Sig::WithoutRuntime.sig { params(out: T.any(StringIO, IO), err: T.any(StringIO, IO), block: T.proc.void).void }

[View source]

424
425
426
427
428
429
430
431
432
433
# File 'lib/kubernetes-cli.rb', line 424

def with_pipes(out = STDOUT, err = STDERR, &block)
  previous_stdout = self.stdout
  previous_stderr = self.stderr
  self.stdout = out
  self.stderr = err
  yield
ensure
  self.stdout = previous_stdout
  self.stderr = previous_stderr
end