walheim 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/README.md +2 -0
- data/lib/walheim/cli/base_command.rb +98 -99
- data/lib/walheim/cli/helpers.rb +17 -17
- data/lib/walheim/cli/legacy_context.rb +54 -54
- data/lib/walheim/cli/resource_command.rb +11 -9
- data/lib/walheim/cli.rb +64 -19
- data/lib/walheim/cluster_resource.rb +5 -5
- data/lib/walheim/config.rb +36 -34
- data/lib/walheim/handler_registry.rb +2 -3
- data/lib/walheim/namespaced_resource.rb +40 -20
- data/lib/walheim/resource.rb +30 -14
- data/lib/walheim/resources/apps.rb +493 -121
- data/lib/walheim/resources/configmaps.rb +7 -7
- data/lib/walheim/resources/namespaces.rb +271 -28
- data/lib/walheim/resources/secrets.rb +9 -9
- data/lib/walheim/sync.rb +5 -5
- data/lib/walheim/version.rb +1 -1
- data/lib/walheim.rb +12 -12
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c859436cfcc9582a4a875cf547855472d592b37e391f58abadd0003943272d1d
|
|
4
|
+
data.tar.gz: 15b5ad58f1c94475882e31c41c203f6a8446a63629ed7543957fc3244282be2b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b4c2b0a0ff5d4e6ca42d2ac2159c85689fc7faca2f633061d11b8d3cb8a2cf3bf2d4e9d07c35ca6d2abfb9768fbdcaacd49a0ccb673ba0b0cab55da3ec80c5ba
|
|
7
|
+
data.tar.gz: 2c1c9369e7372cf6c21d1771870e805e43f10a8a082dc886d4a18e6f7ad70bd272e50bb3463c6cafeb8a37acf5a351b0d7efe5ba12b070c6ae45092d92e4d375
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "helpers"
|
|
4
4
|
|
|
5
5
|
module Walheim
|
|
6
6
|
module BaseCommand
|
|
@@ -9,35 +9,39 @@ module Walheim
|
|
|
9
9
|
handler_info = Walheim::HandlerRegistry.get(kind)
|
|
10
10
|
unless handler_info
|
|
11
11
|
warn "Error: unknown kind '#{kind}'"
|
|
12
|
-
warn
|
|
13
|
-
warn
|
|
12
|
+
warn ""
|
|
13
|
+
warn "Available kinds:"
|
|
14
14
|
Walheim::HandlerRegistry.all_visible.each { |h| warn " #{h[:name]}" }
|
|
15
15
|
exit 1
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# 2. Check operation support
|
|
19
|
+
handler_class = handler_info[:handler]
|
|
19
20
|
unless Walheim::HandlerRegistry.supports_operation?(kind, operation)
|
|
20
21
|
warn "Error: #{operation} not supported for #{kind}"
|
|
21
22
|
exit 1
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
# 3.
|
|
25
|
+
# 3. Get operation metadata
|
|
26
|
+
op_metadata = handler_class.operation_info[operation]
|
|
27
|
+
unless op_metadata
|
|
28
|
+
warn "Error: operation metadata missing for #{operation}"
|
|
29
|
+
exit 1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# 4. Resolve data directory from context
|
|
25
33
|
data_dir = resolve_data_dir(options, parent_options)
|
|
26
34
|
|
|
27
|
-
#
|
|
28
|
-
handler =
|
|
35
|
+
# 5. Initialize handler
|
|
36
|
+
handler = handler_class.new(data_dir: data_dir)
|
|
29
37
|
|
|
30
|
-
#
|
|
31
|
-
if handler.is_a?(Walheim::NamespacedResource)
|
|
32
|
-
validate_namespace_options!(operation, kind, name, options)
|
|
33
|
-
end
|
|
38
|
+
# 6. Validate namespace requirements
|
|
39
|
+
validate_namespace_requirements!(operation, kind, name, options, op_metadata) if handler.is_a?(Walheim::NamespacedResource)
|
|
34
40
|
|
|
35
|
-
#
|
|
36
|
-
|
|
41
|
+
# 7. Dispatch to handler using metadata
|
|
42
|
+
dispatch_operation(handler, operation, name, options, handler_info, op_metadata)
|
|
37
43
|
end
|
|
38
44
|
|
|
39
|
-
private
|
|
40
|
-
|
|
41
45
|
def self.resolve_data_dir(options, parent_options)
|
|
42
46
|
# Merge options
|
|
43
47
|
all_options = parent_options.merge(options)
|
|
@@ -51,125 +55,120 @@ module Walheim
|
|
|
51
55
|
if context_name
|
|
52
56
|
config.data_dir(context_name)
|
|
53
57
|
elsif all_options[:data_dir]
|
|
54
|
-
warn
|
|
58
|
+
warn "Warning: --data-dir is deprecated. Use contexts."
|
|
55
59
|
all_options[:data_dir]
|
|
56
60
|
else
|
|
57
|
-
warn
|
|
58
|
-
warn
|
|
59
|
-
warn
|
|
60
|
-
warn
|
|
61
|
+
warn "Error: No Walheim configuration found."
|
|
62
|
+
warn ""
|
|
63
|
+
warn "Create your first context:"
|
|
64
|
+
warn " whctl context new <name> --data-dir <path>"
|
|
61
65
|
exit 1
|
|
62
66
|
end
|
|
63
67
|
rescue Walheim::Config::ConfigError, Walheim::Config::ValidationError
|
|
64
68
|
if all_options[:data_dir]
|
|
65
|
-
warn
|
|
69
|
+
warn "Warning: --data-dir is deprecated."
|
|
66
70
|
all_options[:data_dir]
|
|
67
71
|
else
|
|
68
|
-
warn
|
|
69
|
-
warn
|
|
70
|
-
warn
|
|
71
|
-
warn
|
|
72
|
+
warn "Error: No Walheim configuration found."
|
|
73
|
+
warn ""
|
|
74
|
+
warn "Create your first context:"
|
|
75
|
+
warn " whctl context new <name> --data-dir <path>"
|
|
72
76
|
exit 1
|
|
73
77
|
end
|
|
74
78
|
end
|
|
75
79
|
end
|
|
76
80
|
|
|
77
|
-
def self.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return unless requires_namespace.include?(operation)
|
|
81
|
+
def self.validate_namespace_requirements!(operation, kind, _name, options, op_metadata)
|
|
82
|
+
dispatch_meta = op_metadata[:dispatch] || {}
|
|
83
|
+
namespace_handling = dispatch_meta[:namespace_handling]
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
case namespace_handling
|
|
86
|
+
when :optional_with_all
|
|
87
|
+
# Operations like get can use --all or -n
|
|
84
88
|
return if options[:all] || options[:namespace]
|
|
85
|
-
|
|
86
|
-
warn "
|
|
87
|
-
warn "Usage: whctl
|
|
89
|
+
|
|
90
|
+
warn "Error: either -n {namespace} or --all/-A flag is required"
|
|
91
|
+
warn "Usage: whctl #{operation} #{kind} -n {namespace}"
|
|
92
|
+
warn "Usage: whctl #{operation} #{kind} --all"
|
|
88
93
|
exit 1
|
|
89
|
-
|
|
94
|
+
when :required
|
|
95
|
+
# Operations require namespace
|
|
96
|
+
return if options[:namespace]
|
|
90
97
|
|
|
91
|
-
|
|
92
|
-
unless options[:namespace]
|
|
93
|
-
warn 'Error: -n {namespace} is required'
|
|
98
|
+
warn "Error: -n {namespace} is required"
|
|
94
99
|
warn "Usage: whctl #{operation} #{kind} {name} -n {namespace}"
|
|
95
100
|
exit 1
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def self.dispatch_to_handler(handler, operation, name, options, handler_info)
|
|
100
|
-
case operation
|
|
101
|
-
when :get
|
|
102
|
-
dispatch_get(handler, name, options, handler_info)
|
|
103
|
-
when :apply
|
|
104
|
-
dispatch_apply(handler, name, options, handler_info)
|
|
105
|
-
when :delete
|
|
106
|
-
handler.delete(namespace: options[:namespace], name: name)
|
|
107
|
-
when :create
|
|
108
|
-
# Special case: create namespace
|
|
109
|
-
handler.create(name: name, username: options[:username], hostname: options[:hostname])
|
|
110
|
-
when :import
|
|
111
|
-
# Special case: import app
|
|
112
|
-
compose_manifest = Walheim::Helpers.read_yaml_input(options[:file])
|
|
113
|
-
handler.import(namespace: options[:namespace], name: name, compose_manifest: compose_manifest)
|
|
114
|
-
when :start, :pause, :stop
|
|
115
|
-
handler.send(operation, namespace: options[:namespace], name: name)
|
|
116
|
-
when :logs
|
|
117
|
-
log_opts = {}
|
|
118
|
-
log_opts[:follow] = options[:follow] if options[:follow]
|
|
119
|
-
log_opts[:tail] = options[:tail] if options[:tail]
|
|
120
|
-
log_opts[:timestamps] = options[:timestamps] if options[:timestamps]
|
|
121
|
-
handler.logs(namespace: options[:namespace], name: name, **log_opts)
|
|
101
|
+
when nil
|
|
102
|
+
# No namespace validation needed
|
|
103
|
+
nil
|
|
122
104
|
else
|
|
123
|
-
warn "Error:
|
|
105
|
+
warn "Error: unknown namespace_handling: #{namespace_handling}"
|
|
124
106
|
exit 1
|
|
125
107
|
end
|
|
126
108
|
end
|
|
127
109
|
|
|
128
|
-
def self.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
110
|
+
def self.dispatch_operation(handler, operation, name, options, handler_info, op_metadata)
|
|
111
|
+
dispatch_meta = op_metadata[:dispatch] || {}
|
|
112
|
+
method_name = dispatch_meta[:method] || operation
|
|
113
|
+
|
|
114
|
+
# Build method parameters
|
|
115
|
+
params = build_method_params(name, options, dispatch_meta)
|
|
116
|
+
|
|
117
|
+
# Call handler method
|
|
118
|
+
result = handler.send(method_name, **params)
|
|
119
|
+
|
|
120
|
+
# Handle output formatting
|
|
121
|
+
handle_output(result, handler, handler_info, options, dispatch_meta)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def self.build_method_params(name, options, dispatch_meta)
|
|
125
|
+
params = {}
|
|
126
|
+
|
|
127
|
+
# Add positional params (like :name)
|
|
128
|
+
positional_params = dispatch_meta[:params] || []
|
|
129
|
+
positional_params.each do |param_name|
|
|
130
|
+
case param_name
|
|
131
|
+
when :name
|
|
132
|
+
params[:name] = name
|
|
135
133
|
else
|
|
136
|
-
|
|
134
|
+
params[param_name] = options[param_name]
|
|
137
135
|
end
|
|
138
|
-
Walheim::Helpers.print_resources_table(result, options[:all], handler_info[:name])
|
|
139
136
|
end
|
|
140
|
-
end
|
|
141
137
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
138
|
+
# Add named params from options
|
|
139
|
+
named_params = dispatch_meta[:named_params] || {}
|
|
140
|
+
named_params.each do |param_name, option_key|
|
|
141
|
+
option_value = options[option_key]
|
|
146
142
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
143
|
+
# Handle file readers
|
|
144
|
+
if dispatch_meta[:file_reader] == param_name && option_value
|
|
145
|
+
option_value = Walheim::Helpers.read_yaml_input(option_value)
|
|
146
|
+
end
|
|
150
147
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
end
|
|
148
|
+
# Always include declared parameters (handlers expect them as keyword args)
|
|
149
|
+
params[param_name] = option_value
|
|
150
|
+
end
|
|
155
151
|
|
|
156
|
-
|
|
152
|
+
params
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def self.handle_output(result, handler, handler_info, options, dispatch_meta)
|
|
156
|
+
output_type = dispatch_meta[:output]
|
|
157
|
+
|
|
158
|
+
case output_type
|
|
159
|
+
when :table
|
|
160
|
+
# Table output for get operations
|
|
161
|
+
if handler.is_a?(Walheim::ClusterResource)
|
|
162
|
+
Walheim::Helpers.print_cluster_resources_table(result, handler_info[:name])
|
|
157
163
|
else
|
|
158
|
-
|
|
159
|
-
name = manifest_data['metadata']['name']
|
|
160
|
-
unless name
|
|
161
|
-
warn 'Error: Manifest must contain metadata.name'
|
|
162
|
-
exit 1
|
|
163
|
-
end
|
|
164
|
-
handler.apply(name: name, manifest_source: options[:file])
|
|
164
|
+
Walheim::Helpers.print_resources_table(result, options[:all], handler_info[:name])
|
|
165
165
|
end
|
|
166
|
+
when nil
|
|
167
|
+
# No output handling needed (handler prints directly)
|
|
168
|
+
nil
|
|
166
169
|
else
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
handler.apply(namespace: options[:namespace], name: name)
|
|
170
|
-
else
|
|
171
|
-
handler.apply(name: name)
|
|
172
|
-
end
|
|
170
|
+
warn "Error: unknown output type: #{output_type}"
|
|
171
|
+
exit 1
|
|
173
172
|
end
|
|
174
173
|
end
|
|
175
174
|
end
|
data/lib/walheim/cli/helpers.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "terminal-table"
|
|
4
|
+
require "yaml"
|
|
5
5
|
|
|
6
6
|
module Walheim
|
|
7
7
|
module Helpers
|
|
@@ -22,31 +22,31 @@ module Walheim
|
|
|
22
22
|
summary_fields = result.first[:summary].keys
|
|
23
23
|
|
|
24
24
|
# Build header row
|
|
25
|
-
if all_namespaces
|
|
26
|
-
|
|
25
|
+
headers = if all_namespaces
|
|
26
|
+
%w[NAMESPACE NAME] + summary_fields.map(&:to_s).map(&:upcase)
|
|
27
27
|
else
|
|
28
|
-
|
|
28
|
+
[ "NAME" ] + summary_fields.map(&:to_s).map(&:upcase)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# Build data rows
|
|
32
32
|
rows = result.map do |resource|
|
|
33
33
|
row = if all_namespaces
|
|
34
|
-
|
|
34
|
+
[ resource[:namespace], resource[:name] ]
|
|
35
35
|
else
|
|
36
|
-
|
|
36
|
+
[ resource[:name] ]
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# Add summary field values
|
|
40
|
-
summary_values = summary_fields.map { |field| resource[:summary][field] ||
|
|
40
|
+
summary_values = summary_fields.map { |field| resource[:summary][field] || "N/A" }
|
|
41
41
|
row + summary_values
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
all_rows = [headers] + rows
|
|
44
|
+
all_rows = [ headers ] + rows
|
|
45
45
|
|
|
46
46
|
table = Terminal::Table.new do |t|
|
|
47
47
|
t.rows = all_rows
|
|
48
48
|
t.style = {
|
|
49
|
-
border_x:
|
|
49
|
+
border_x: "", border_y: "", border_i: "",
|
|
50
50
|
padding_left: 0, padding_right: 3,
|
|
51
51
|
border_top: false, border_bottom: false,
|
|
52
52
|
all_separators: false
|
|
@@ -73,23 +73,23 @@ module Walheim
|
|
|
73
73
|
summary_fields = result.first[:summary].keys
|
|
74
74
|
|
|
75
75
|
# Build header row (no NAMESPACE column for cluster resources)
|
|
76
|
-
headers = [
|
|
76
|
+
headers = [ "NAME" ] + summary_fields.map(&:to_s).map(&:upcase)
|
|
77
77
|
|
|
78
78
|
# Build data rows
|
|
79
79
|
rows = result.map do |resource|
|
|
80
|
-
row = [resource[:name]]
|
|
80
|
+
row = [ resource[:name] ]
|
|
81
81
|
|
|
82
82
|
# Add summary field values
|
|
83
|
-
summary_values = summary_fields.map { |field| resource[:summary][field] ||
|
|
83
|
+
summary_values = summary_fields.map { |field| resource[:summary][field] || "N/A" }
|
|
84
84
|
row + summary_values
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
-
all_rows = [headers] + rows
|
|
87
|
+
all_rows = [ headers ] + rows
|
|
88
88
|
|
|
89
89
|
table = Terminal::Table.new do |t|
|
|
90
90
|
t.rows = all_rows
|
|
91
91
|
t.style = {
|
|
92
|
-
border_x:
|
|
92
|
+
border_x: "", border_y: "", border_i: "",
|
|
93
93
|
padding_left: 0, padding_right: 3,
|
|
94
94
|
border_top: false, border_bottom: false,
|
|
95
95
|
all_separators: false
|
|
@@ -101,9 +101,9 @@ module Walheim
|
|
|
101
101
|
|
|
102
102
|
# Read YAML from file or stdin
|
|
103
103
|
def self.read_yaml_input(file_path)
|
|
104
|
-
if file_path ==
|
|
104
|
+
if file_path == "-"
|
|
105
105
|
# Read from stdin
|
|
106
|
-
YAML.
|
|
106
|
+
YAML.safe_load($stdin.read)
|
|
107
107
|
else
|
|
108
108
|
# Read from file
|
|
109
109
|
YAML.load_file(file_path)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "optparse"
|
|
4
|
+
require "terminal-table"
|
|
5
5
|
|
|
6
6
|
module Walheim
|
|
7
7
|
module LegacyContext
|
|
@@ -9,12 +9,12 @@ module Walheim
|
|
|
9
9
|
options = {}
|
|
10
10
|
|
|
11
11
|
# Remove 'context' from argv since it's already been identified
|
|
12
|
-
argv.shift if argv[0] ==
|
|
12
|
+
argv.shift if argv[0] == "context"
|
|
13
13
|
|
|
14
14
|
# Parse global flags
|
|
15
15
|
global_parser = OptionParser.new do |opts|
|
|
16
|
-
opts.on(
|
|
17
|
-
opts.on(
|
|
16
|
+
opts.on("--whconfig PATH", "Alternate config file path") { |v| options[:whconfig] = v }
|
|
17
|
+
opts.on("-d DIR", "--data-dir DIR", "Data directory") { |v| options[:data_dir] = v }
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# Parse global flags (use parse! to consume all flags)
|
|
@@ -30,17 +30,17 @@ module Walheim
|
|
|
30
30
|
context_name = argv[1]
|
|
31
31
|
|
|
32
32
|
case subcommand
|
|
33
|
-
when
|
|
33
|
+
when "new"
|
|
34
34
|
# whctl context new {name} --data-dir {path}
|
|
35
35
|
unless context_name
|
|
36
|
-
warn
|
|
37
|
-
warn
|
|
36
|
+
warn "Error: context name is required"
|
|
37
|
+
warn "Usage: whctl context new {name} --data-dir {path}"
|
|
38
38
|
exit 1
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
unless options[:data_dir]
|
|
42
|
-
warn
|
|
43
|
-
warn
|
|
42
|
+
warn "Error: --data-dir flag is required"
|
|
43
|
+
warn "Usage: whctl context new {name} --data-dir {path}"
|
|
44
44
|
exit 1
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -48,19 +48,19 @@ module Walheim
|
|
|
48
48
|
expanded_data_dir = File.expand_path(options[:data_dir])
|
|
49
49
|
unless Dir.exist?(expanded_data_dir)
|
|
50
50
|
warn "Error: data directory '#{expanded_data_dir}' does not exist"
|
|
51
|
-
warn
|
|
52
|
-
warn
|
|
51
|
+
warn ""
|
|
52
|
+
warn "Please create the directory first or provide a valid path"
|
|
53
53
|
exit 1
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# Check for namespaces subdirectory
|
|
57
|
-
namespaces_path = File.join(expanded_data_dir,
|
|
57
|
+
namespaces_path = File.join(expanded_data_dir, "namespaces")
|
|
58
58
|
unless Dir.exist?(namespaces_path)
|
|
59
59
|
warn "Warning: data directory does not contain 'namespaces' subdirectory"
|
|
60
60
|
warn "Expected path: #{namespaces_path}"
|
|
61
|
-
warn
|
|
62
|
-
warn
|
|
63
|
-
warn
|
|
61
|
+
warn ""
|
|
62
|
+
warn "This directory should contain your homelab configuration."
|
|
63
|
+
warn "Creating namespaces directory..."
|
|
64
64
|
Dir.mkdir(namespaces_path)
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -81,34 +81,34 @@ module Walheim
|
|
|
81
81
|
exit 1
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
when
|
|
84
|
+
when "list"
|
|
85
85
|
# whctl context list
|
|
86
86
|
config = Walheim::Config.new(config_path: options[:whconfig])
|
|
87
87
|
|
|
88
88
|
unless Walheim::Config.exists?(config_path: options[:whconfig])
|
|
89
|
-
warn
|
|
90
|
-
warn
|
|
91
|
-
warn
|
|
92
|
-
warn
|
|
89
|
+
warn "No Walheim configuration found."
|
|
90
|
+
warn ""
|
|
91
|
+
warn "Create your first context:"
|
|
92
|
+
warn " whctl context new <name> --data-dir <path>"
|
|
93
93
|
exit 1
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
contexts = config.list_contexts
|
|
97
97
|
if contexts.empty?
|
|
98
|
-
puts
|
|
98
|
+
puts "No contexts configured."
|
|
99
99
|
exit 0
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
rows = contexts.map do |ctx|
|
|
103
|
-
active_marker = ctx[
|
|
104
|
-
[active_marker, ctx[
|
|
103
|
+
active_marker = ctx["active"] ? "*" : ""
|
|
104
|
+
[ active_marker, ctx["name"], ctx["dataDir"] ]
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
table = Terminal::Table.new do |t|
|
|
108
|
-
t.headings = [
|
|
108
|
+
t.headings = [ "CURRENT", "NAME", "DATA DIRECTORY" ]
|
|
109
109
|
t.rows = rows
|
|
110
110
|
t.style = {
|
|
111
|
-
border_x:
|
|
111
|
+
border_x: "", border_y: "", border_i: "",
|
|
112
112
|
padding_left: 0, padding_right: 3,
|
|
113
113
|
border_top: false, border_bottom: false,
|
|
114
114
|
all_separators: false
|
|
@@ -117,11 +117,11 @@ module Walheim
|
|
|
117
117
|
|
|
118
118
|
puts table
|
|
119
119
|
|
|
120
|
-
when
|
|
120
|
+
when "use"
|
|
121
121
|
# whctl context use {name}
|
|
122
122
|
unless context_name
|
|
123
|
-
warn
|
|
124
|
-
warn
|
|
123
|
+
warn "Error: context name is required"
|
|
124
|
+
warn "Usage: whctl context use {name}"
|
|
125
125
|
exit 1
|
|
126
126
|
end
|
|
127
127
|
|
|
@@ -136,15 +136,15 @@ module Walheim
|
|
|
136
136
|
exit 1
|
|
137
137
|
end
|
|
138
138
|
|
|
139
|
-
when
|
|
139
|
+
when "current"
|
|
140
140
|
# whctl context current
|
|
141
141
|
config = Walheim::Config.new(config_path: options[:whconfig])
|
|
142
142
|
|
|
143
143
|
unless Walheim::Config.exists?(config_path: options[:whconfig])
|
|
144
|
-
warn
|
|
145
|
-
warn
|
|
146
|
-
warn
|
|
147
|
-
warn
|
|
144
|
+
warn "No Walheim configuration found."
|
|
145
|
+
warn ""
|
|
146
|
+
warn "Create your first context:"
|
|
147
|
+
warn " whctl context new <name> --data-dir <path>"
|
|
148
148
|
exit 1
|
|
149
149
|
end
|
|
150
150
|
|
|
@@ -152,22 +152,22 @@ module Walheim
|
|
|
152
152
|
puts "Current context: #{config.current_context}"
|
|
153
153
|
puts "Data directory: #{config.data_dir}"
|
|
154
154
|
else
|
|
155
|
-
puts
|
|
156
|
-
puts
|
|
157
|
-
puts
|
|
155
|
+
puts "No active context selected."
|
|
156
|
+
puts ""
|
|
157
|
+
puts "Available contexts:"
|
|
158
158
|
config.list_contexts.each do |ctx|
|
|
159
159
|
puts " - #{ctx['name']}"
|
|
160
160
|
end
|
|
161
|
-
puts
|
|
162
|
-
puts
|
|
163
|
-
puts
|
|
161
|
+
puts ""
|
|
162
|
+
puts "Select a context:"
|
|
163
|
+
puts " whctl context use <context-name>"
|
|
164
164
|
end
|
|
165
165
|
|
|
166
|
-
when
|
|
166
|
+
when "delete"
|
|
167
167
|
# whctl context delete {name}
|
|
168
168
|
unless context_name
|
|
169
|
-
warn
|
|
170
|
-
warn
|
|
169
|
+
warn "Error: context name is required"
|
|
170
|
+
warn "Usage: whctl context delete {name}"
|
|
171
171
|
exit 1
|
|
172
172
|
end
|
|
173
173
|
|
|
@@ -180,10 +180,10 @@ module Walheim
|
|
|
180
180
|
|
|
181
181
|
# Show warning if this was the active context
|
|
182
182
|
unless config.current_context
|
|
183
|
-
puts
|
|
184
|
-
puts
|
|
185
|
-
puts
|
|
186
|
-
puts
|
|
183
|
+
puts ""
|
|
184
|
+
puts "Note: This was your active context."
|
|
185
|
+
puts "Select a new context with:"
|
|
186
|
+
puts " whctl context use <context-name>"
|
|
187
187
|
end
|
|
188
188
|
rescue Walheim::Config::ConfigError => e
|
|
189
189
|
warn "Error: #{e.message}"
|
|
@@ -192,13 +192,13 @@ module Walheim
|
|
|
192
192
|
|
|
193
193
|
else
|
|
194
194
|
warn "Error: unknown context subcommand '#{subcommand}'"
|
|
195
|
-
warn
|
|
196
|
-
warn
|
|
197
|
-
warn
|
|
198
|
-
warn
|
|
199
|
-
warn
|
|
200
|
-
warn
|
|
201
|
-
warn
|
|
195
|
+
warn ""
|
|
196
|
+
warn "Available context commands:"
|
|
197
|
+
warn " whctl context new {name} --data-dir {path}"
|
|
198
|
+
warn " whctl context list"
|
|
199
|
+
warn " whctl context use {name}"
|
|
200
|
+
warn " whctl context current"
|
|
201
|
+
warn " whctl context delete {name}"
|
|
202
202
|
exit 1
|
|
203
203
|
end
|
|
204
204
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "base_command"
|
|
4
4
|
|
|
5
5
|
module Walheim
|
|
6
6
|
module ResourceCommand
|
|
@@ -10,7 +10,7 @@ module Walheim
|
|
|
10
10
|
return if handlers.empty?
|
|
11
11
|
|
|
12
12
|
# Build command description
|
|
13
|
-
descriptions = handlers.map { |h| h[:name] }.join(
|
|
13
|
+
descriptions = handlers.map { |h| h[:name] }.join(", ")
|
|
14
14
|
desc_text = "#{operation.to_s.capitalize} resources (#{descriptions})"
|
|
15
15
|
|
|
16
16
|
# Define Thor command
|
|
@@ -21,12 +21,10 @@ module Walheim
|
|
|
21
21
|
all_options = {}
|
|
22
22
|
handlers.each do |handler_info|
|
|
23
23
|
handler_class = handler_info[:handler]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
end
|
|
24
|
+
next unless handler_class.respond_to?(:operation_info)
|
|
25
|
+
|
|
26
|
+
op_metadata = handler_class.operation_info[operation]
|
|
27
|
+
all_options.merge!(op_metadata[:options]) if op_metadata && op_metadata[:options]
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
# Register options with Thor
|
|
@@ -43,7 +41,11 @@ module Walheim
|
|
|
43
41
|
kind: kind,
|
|
44
42
|
name: name,
|
|
45
43
|
options: options,
|
|
46
|
-
parent_options: self.class.class_options.transform_keys(&:to_sym).transform_values
|
|
44
|
+
parent_options: self.class.class_options.transform_keys(&:to_sym).transform_values do |v|
|
|
45
|
+
options[v.name]
|
|
46
|
+
rescue StandardError
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
47
49
|
)
|
|
48
50
|
end
|
|
49
51
|
end
|