kube_kubectl 0.2.0 → 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 +4 -4
- data/lib/kube/ctl/command_node.rb +89 -0
- data/lib/kube/ctl/instance.rb +55 -0
- data/lib/kube/ctl/query_builder.rb +35 -0
- data/lib/kube/ctl/resource_selector.rb +19 -0
- data/lib/kube/ctl/tree_node.rb +51 -0
- data/lib/kube/ctl/version.rb +1 -1
- data/lib/kube/ctl.rb +6 -1
- data/lib/kube.rb +9 -0
- metadata +7 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 575707668cbc10ea9821e3bff81c53b0765c3e8e29dcef09439501577bf9757b
|
|
4
|
+
data.tar.gz: 954b60d822db40613ca1b08aabe758c5316823dcb59ac11bb935d7242e531ef8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 42067d867db7414f85efdaecc747a8b9a6dd91f8a7877b097498e7df56bfdd220d7c3caa177d2dfc4434ab0af4465481a31deb8a3ab5968572f7c5dbf61bab79
|
|
7
|
+
data.tar.gz: fd3b44cbb6aa6d3202e65113b18bb69280f317fc6cda3b266bb6fd3d8d1e1badc3e7e3ae0b989fd2ca3d9b598b1be1fd9ed20db7688317d9ed16366e81b12b82
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kube
|
|
4
|
+
module Ctl
|
|
5
|
+
class CommandNode
|
|
6
|
+
include Enumerable
|
|
7
|
+
|
|
8
|
+
BLANK_DATA = { commands: [], resource: nil, args: [], flags: {} }.freeze
|
|
9
|
+
|
|
10
|
+
attr_reader :command_data
|
|
11
|
+
|
|
12
|
+
def initialize(current_node:, command_data: BLANK_DATA)
|
|
13
|
+
@current_node = current_node
|
|
14
|
+
@command_data = command_data
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def flag(key, value = nil)
|
|
18
|
+
self.class.new(
|
|
19
|
+
current_node: @current_node,
|
|
20
|
+
command_data: @command_data.merge(
|
|
21
|
+
flags: @command_data[:flags].merge(key.to_s.tr('_', '-') => value)
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def each(&block)
|
|
27
|
+
to_a.each(&block)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_a
|
|
31
|
+
QueryBuilder.new(@command_data).to_a
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_s
|
|
35
|
+
QueryBuilder.new(@command_data).to_s
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def inspect
|
|
39
|
+
"#<#{self.class.name} #{self}>"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def method_missing(name, *args, &block)
|
|
43
|
+
segment = name.to_s.tr('_', '-')
|
|
44
|
+
child = @current_node.children[segment]
|
|
45
|
+
|
|
46
|
+
if child&.command?
|
|
47
|
+
self.class.new(
|
|
48
|
+
current_node: child,
|
|
49
|
+
command_data: @command_data.merge(
|
|
50
|
+
commands: @command_data[:commands] + [segment],
|
|
51
|
+
args: @command_data[:args] + args.map(&:to_s)
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
elsif child&.resource?
|
|
55
|
+
self.class.new(
|
|
56
|
+
current_node: child,
|
|
57
|
+
command_data: @command_data.merge(
|
|
58
|
+
resource: (@command_data[:resource] || ResourceSelector.new) + [segment],
|
|
59
|
+
args: @command_data[:args] + args.map(&:to_s)
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
elsif @current_node.resource? || @current_node.children.empty?
|
|
63
|
+
# Leaf command or already in resource mode — free-form resource segment
|
|
64
|
+
self.class.new(
|
|
65
|
+
current_node: TreeNode.new(name: segment, type: :resource),
|
|
66
|
+
command_data: @command_data.merge(
|
|
67
|
+
resource: (@command_data[:resource] || ResourceSelector.new) + [segment],
|
|
68
|
+
args: @command_data[:args] + args.map(&:to_s)
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
elsif Enumerable.method_defined?(name)
|
|
72
|
+
to_a.public_send(name, *args, &block)
|
|
73
|
+
else
|
|
74
|
+
super
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def respond_to_missing?(name, include_private = false)
|
|
79
|
+
segment = name.to_s.tr('_', '-')
|
|
80
|
+
|
|
81
|
+
@current_node.children.key?(segment) ||
|
|
82
|
+
@current_node.resource? ||
|
|
83
|
+
@current_node.children.empty? ||
|
|
84
|
+
Enumerable.method_defined?(name) ||
|
|
85
|
+
super
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Kube
|
|
6
|
+
module Ctl
|
|
7
|
+
class Instance
|
|
8
|
+
GEM_ROOT = File.expand_path('../../..', __dir__)
|
|
9
|
+
|
|
10
|
+
COMMAND_TREE = JSON.parse(
|
|
11
|
+
File.read(File.join(GEM_ROOT, 'data', 'kubectl-command-tree-v1-minimal.json'))
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
ROOT = TreeNode.new(
|
|
15
|
+
name: 'kubectl',
|
|
16
|
+
type: :command,
|
|
17
|
+
children: TreeNode.build(COMMAND_TREE)
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
attr_reader :kubeconfig
|
|
21
|
+
|
|
22
|
+
# When kubeconfig is nil, no --kubeconfig flag is passed and
|
|
23
|
+
# kubectl falls back to its own default (~/.kube/config).
|
|
24
|
+
def initialize(kubeconfig: ENV['KUBECONFIG'])
|
|
25
|
+
@kubeconfig = kubeconfig
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def method_missing(name, *args, &block)
|
|
29
|
+
root_node.public_send(name, *args, &block)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def respond_to_missing?(name, include_private = false)
|
|
33
|
+
root_node.respond_to?(name) || super
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def inspect
|
|
37
|
+
"#<#{self.class.name} kubeconfig=#{@kubeconfig.inspect}>"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def root_node
|
|
43
|
+
CommandNode.new(current_node: ROOT, command_data: initial_command_data)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def initial_command_data
|
|
47
|
+
CommandNode::BLANK_DATA.merge(flags: initial_flags)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def initial_flags
|
|
51
|
+
@kubeconfig ? { 'kubeconfig' => @kubeconfig } : {}
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
module Kube
|
|
6
|
+
module Ctl
|
|
7
|
+
class QueryBuilder
|
|
8
|
+
def initialize(command_data)
|
|
9
|
+
@commands = command_data[:commands] || []
|
|
10
|
+
@resource = command_data[:resource]
|
|
11
|
+
@args = command_data[:args] || []
|
|
12
|
+
@flags = command_data[:flags] || {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
['kubectl', *@commands, *resource_arg, *@args, *rendered_flags].join(' ')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_a
|
|
20
|
+
stdout, _status = Open3.capture2('kubectl', *@commands, *resource_arg, *@args, *rendered_flags)
|
|
21
|
+
stdout.lines.map(&:chomp)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def resource_arg
|
|
27
|
+
@resource ? [@resource.to_s] : []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def rendered_flags
|
|
31
|
+
@flags.flat_map { |k, v| v.nil? ? ["--#{k}"] : ["--#{k}", v.to_s] }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kube
|
|
4
|
+
module Ctl
|
|
5
|
+
class ResourceSelector < Array
|
|
6
|
+
def +(other)
|
|
7
|
+
self.class.new(super)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_s
|
|
11
|
+
join('.')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_regex
|
|
15
|
+
Regexp.new(map { |s| Regexp.escape(s) }.join('.*\.'))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kube
|
|
4
|
+
module Ctl
|
|
5
|
+
class TreeNode
|
|
6
|
+
# Commands whose leaf children are resource types.
|
|
7
|
+
# Non-leaf children (those with their own subtree) remain commands.
|
|
8
|
+
RESOURCE_PARENTS = %w[
|
|
9
|
+
create
|
|
10
|
+
create/secret
|
|
11
|
+
create/service
|
|
12
|
+
top
|
|
13
|
+
].freeze
|
|
14
|
+
|
|
15
|
+
attr_reader :name, :type, :children
|
|
16
|
+
|
|
17
|
+
def initialize(name:, type:, children: {})
|
|
18
|
+
@name = name.freeze
|
|
19
|
+
@type = type
|
|
20
|
+
@children = children.freeze
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def command? = type == :command
|
|
24
|
+
def resource? = type == :resource
|
|
25
|
+
|
|
26
|
+
# Recursively build a children hash of TreeNodes from the parsed JSON.
|
|
27
|
+
# parent_path tracks position in the tree to determine child types.
|
|
28
|
+
def self.build(hash, parent_path: nil)
|
|
29
|
+
hash.each_with_object({}) do |(key, subtree), children|
|
|
30
|
+
name = key.to_s
|
|
31
|
+
current_path = [parent_path, name].compact.join('/')
|
|
32
|
+
leaf = subtree.empty?
|
|
33
|
+
|
|
34
|
+
# Under a resource parent, leaf nodes are resources, non-leaves are commands.
|
|
35
|
+
# Everywhere else, everything is a command.
|
|
36
|
+
child_type = if RESOURCE_PARENTS.include?(parent_path.to_s) && leaf
|
|
37
|
+
:resource
|
|
38
|
+
else
|
|
39
|
+
:command
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
children[name] = new(
|
|
43
|
+
name: name,
|
|
44
|
+
type: child_type,
|
|
45
|
+
children: build(subtree, parent_path: current_path)
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/kube/ctl/version.rb
CHANGED
data/lib/kube/ctl.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative 'ctl/version'
|
|
4
|
+
require_relative 'ctl/tree_node'
|
|
5
|
+
require_relative 'ctl/resource_selector'
|
|
6
|
+
require_relative 'ctl/query_builder'
|
|
7
|
+
require_relative 'ctl/command_node'
|
|
8
|
+
require_relative 'ctl/instance'
|
|
4
9
|
|
|
5
10
|
module Kube
|
|
6
11
|
module Ctl
|
data/lib/kube.rb
ADDED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kube_kubectl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nathan K
|
|
@@ -81,7 +81,13 @@ files:
|
|
|
81
81
|
- flake.nix
|
|
82
82
|
- kube_ctl.gemspec
|
|
83
83
|
- kube_ctl.gemspec.erb
|
|
84
|
+
- lib/kube.rb
|
|
84
85
|
- lib/kube/ctl.rb
|
|
86
|
+
- lib/kube/ctl/command_node.rb
|
|
87
|
+
- lib/kube/ctl/instance.rb
|
|
88
|
+
- lib/kube/ctl/query_builder.rb
|
|
89
|
+
- lib/kube/ctl/resource_selector.rb
|
|
90
|
+
- lib/kube/ctl/tree_node.rb
|
|
85
91
|
- lib/kube/ctl/version.rb
|
|
86
92
|
- lib/kube/ctl/version.rb.erb
|
|
87
93
|
homepage: https://github.com/general-intelligence-systems/kube_ctl
|