kdep 0.1.0 → 0.1.3
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/kdep/cli.rb +2 -0
- data/lib/kdep/commands/apply.rb +19 -1
- data/lib/kdep/commands/bump.rb +53 -24
- data/lib/kdep/commands/dashboard.rb +90 -0
- data/lib/kdep/commands/init.rb +8 -0
- data/lib/kdep/commands/log.rb +7 -2
- data/lib/kdep/commands/migrate.rb +157 -0
- data/lib/kdep/commands/restart.rb +7 -2
- data/lib/kdep/commands/scale.rb +7 -2
- data/lib/kdep/commands/secrets.rb +7 -2
- data/lib/kdep/commands/sh.rb +7 -2
- data/lib/kdep/commands/status.rb +9 -8
- data/lib/kdep/old_format.rb +56 -0
- data/lib/kdep/version.rb +1 -1
- data/lib/kdep.rb +3 -0
- data/templates/presets/custom +3 -0
- metadata +14 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed01f5bcc6ebac09d59dd1d732d73e1913f29ce3f2a9efc7df67fbb914686973
|
|
4
|
+
data.tar.gz: 8b9191bdad263a0902c76a49ef1446e184ab7eae44a269c39947bff1387863fc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 70b166608d549d46929c98a76b1930a5a23d42a0fbf71d118d649aecbbe7ca694524327b2cb3d58a1c19f1a1dc8bc28ac8a578740ffc3d55bc9cb0f17458c721
|
|
7
|
+
data.tar.gz: eedf3f6bfd98c1bd8820db578a5431abe919f11102575fa6dccbef6f3f2af84411968c797cae193974136749021502325ad270d3c0fdfc54b3c35086156403db
|
data/lib/kdep/cli.rb
CHANGED
data/lib/kdep/commands/apply.rb
CHANGED
|
@@ -60,6 +60,8 @@ module Kdep
|
|
|
60
60
|
writer = Kdep::Writer.new(output_dir)
|
|
61
61
|
writer.clean
|
|
62
62
|
renderer = Kdep::Renderer.new(config, deploy_dir)
|
|
63
|
+
validator = Kdep::Validator.new
|
|
64
|
+
validation_errors = []
|
|
63
65
|
|
|
64
66
|
resources.each_with_index do |resource_name, idx|
|
|
65
67
|
index = idx + 1
|
|
@@ -69,9 +71,25 @@ module Kdep
|
|
|
69
71
|
@ui.error("#{resource_name}: #{e.message}")
|
|
70
72
|
next
|
|
71
73
|
end
|
|
74
|
+
|
|
75
|
+
unless content.nil? || content.strip.empty?
|
|
76
|
+
result = validator.validate(content, resource_name)
|
|
77
|
+
unless result["valid"]
|
|
78
|
+
result["errors"].each do |err|
|
|
79
|
+
validation_errors << "#{resource_name}: #{err}"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
72
84
|
writer.write(resource_name, content, index)
|
|
73
85
|
end
|
|
74
86
|
|
|
87
|
+
unless validation_errors.empty?
|
|
88
|
+
validation_errors.each { |err| @ui.error(err) }
|
|
89
|
+
@ui.error("Manifest validation failed -- fix errors before applying")
|
|
90
|
+
exit 1
|
|
91
|
+
end
|
|
92
|
+
|
|
75
93
|
# Get sorted rendered files
|
|
76
94
|
rendered_files = Dir.glob(File.join(output_dir, "*.yml")).sort
|
|
77
95
|
|
|
@@ -85,7 +103,7 @@ module Kdep
|
|
|
85
103
|
rendered_files.each do |f|
|
|
86
104
|
@ui.info("Would apply: #{File.basename(f)}")
|
|
87
105
|
end
|
|
88
|
-
@ui.info("#{rendered_files.length} files
|
|
106
|
+
@ui.info("#{rendered_files.length} files validated (dry-run, no cluster changes)")
|
|
89
107
|
return
|
|
90
108
|
end
|
|
91
109
|
|
data/lib/kdep/commands/bump.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Kdep
|
|
|
10
10
|
opts.separator "Full pipeline: registry query -> version increment -> build -> push -> render -> apply."
|
|
11
11
|
opts.separator ""
|
|
12
12
|
opts.on("--skip-apply", "Build and push only, skip render+apply")
|
|
13
|
+
opts.on("--dry-run", "Run full pipeline but skip kubectl apply")
|
|
13
14
|
opts.on("--no-dashboard", "Skip TUI dashboard after deploy")
|
|
14
15
|
opts.on("--platform=PLATFORM", "Target platform (e.g., linux/amd64)")
|
|
15
16
|
end
|
|
@@ -50,6 +51,13 @@ module Kdep
|
|
|
50
51
|
exit 1
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
# Pre-apply cluster health check
|
|
55
|
+
dry_run = @command_options[:"dry-run"]
|
|
56
|
+
unless @command_options[:"skip-apply"] || dry_run
|
|
57
|
+
health = Kdep::ClusterHealth.new
|
|
58
|
+
health.report(@ui)
|
|
59
|
+
end
|
|
60
|
+
|
|
53
61
|
image = config["image"] || config["name"]
|
|
54
62
|
registry_url = config["registry"]
|
|
55
63
|
repo_root = File.dirname(kdep_dir)
|
|
@@ -96,6 +104,8 @@ module Kdep
|
|
|
96
104
|
writer = Kdep::Writer.new(output_dir)
|
|
97
105
|
writer.clean
|
|
98
106
|
renderer = Kdep::Renderer.new(config, deploy_dir)
|
|
107
|
+
validator = Kdep::Validator.new
|
|
108
|
+
validation_errors = []
|
|
99
109
|
|
|
100
110
|
resources.each_with_index do |resource_name, idx|
|
|
101
111
|
index = idx + 1
|
|
@@ -105,33 +115,54 @@ module Kdep
|
|
|
105
115
|
@ui.error("#{resource_name}: #{e.message}")
|
|
106
116
|
next
|
|
107
117
|
end
|
|
118
|
+
|
|
119
|
+
unless content.nil? || content.strip.empty?
|
|
120
|
+
result = validator.validate(content, resource_name)
|
|
121
|
+
unless result["valid"]
|
|
122
|
+
result["errors"].each do |err|
|
|
123
|
+
validation_errors << "#{resource_name}: #{err}"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
108
128
|
writer.write(resource_name, content, index)
|
|
109
129
|
end
|
|
110
130
|
|
|
111
|
-
|
|
131
|
+
unless validation_errors.empty?
|
|
132
|
+
validation_errors.each { |err| @ui.error(err) }
|
|
133
|
+
@ui.error("Manifest validation failed -- fix errors before applying")
|
|
134
|
+
exit 1
|
|
135
|
+
end
|
|
136
|
+
|
|
112
137
|
rendered_files = Dir.glob(File.join(output_dir, "*.yml")).sort
|
|
113
|
-
namespace = config["namespace"]
|
|
114
|
-
errors = []
|
|
115
|
-
applied = 0
|
|
116
138
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
@ui.info("applied: #{File.basename(file_path)}")
|
|
121
|
-
applied += 1
|
|
122
|
-
rescue Kdep::Kubectl::Error => e
|
|
123
|
-
errors << { "file" => File.basename(file_path), "error" => e.message }
|
|
124
|
-
@ui.error("#{File.basename(file_path)}: #{e.message}")
|
|
139
|
+
if dry_run
|
|
140
|
+
rendered_files.each do |f|
|
|
141
|
+
@ui.info("Would apply: #{File.basename(f)}")
|
|
125
142
|
end
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
@ui.info("#{rendered_files.length} files validated (dry-run, no cluster changes)")
|
|
144
|
+
else
|
|
145
|
+
# Apply
|
|
146
|
+
namespace = config["namespace"]
|
|
147
|
+
errors = []
|
|
148
|
+
applied = 0
|
|
130
149
|
|
|
131
|
-
|
|
132
|
-
unless @command_options[:"no-dashboard"]
|
|
150
|
+
rendered_files.each do |file_path|
|
|
133
151
|
begin
|
|
134
|
-
|
|
152
|
+
Kdep::Kubectl.apply(file_path, namespace: namespace)
|
|
153
|
+
@ui.info("applied: #{File.basename(file_path)}")
|
|
154
|
+
applied += 1
|
|
155
|
+
rescue Kdep::Kubectl::Error => e
|
|
156
|
+
errors << { "file" => File.basename(file_path), "error" => e.message }
|
|
157
|
+
@ui.error("#{File.basename(file_path)}: #{e.message}")
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
if errors.empty?
|
|
162
|
+
@ui.info("#{applied} files applied, 0 errors")
|
|
163
|
+
|
|
164
|
+
# Launch TUI dashboard for live monitoring
|
|
165
|
+
unless @command_options[:"no-dashboard"]
|
|
135
166
|
dashboard = Kdep::Dashboard.new(
|
|
136
167
|
"name" => config["name"],
|
|
137
168
|
"namespace" => namespace,
|
|
@@ -139,13 +170,11 @@ module Kdep
|
|
|
139
170
|
"image" => image
|
|
140
171
|
)
|
|
141
172
|
dashboard.run
|
|
142
|
-
rescue LoadError, NameError
|
|
143
|
-
# Dashboard not available, skip silently
|
|
144
173
|
end
|
|
174
|
+
else
|
|
175
|
+
@ui.info("#{applied} files applied, #{errors.length} errors")
|
|
176
|
+
exit 1
|
|
145
177
|
end
|
|
146
|
-
else
|
|
147
|
-
@ui.info("#{applied} files applied, #{errors.length} errors")
|
|
148
|
-
exit 1
|
|
149
178
|
end
|
|
150
179
|
end
|
|
151
180
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require "optparse"
|
|
2
|
+
|
|
3
|
+
module Kdep
|
|
4
|
+
module Commands
|
|
5
|
+
class Dashboard
|
|
6
|
+
def self.option_parser
|
|
7
|
+
OptionParser.new do |opts|
|
|
8
|
+
opts.banner = "Usage: kdep dashboard [deploy]"
|
|
9
|
+
opts.separator ""
|
|
10
|
+
opts.separator "Launch TUI dashboard for live cluster monitoring."
|
|
11
|
+
opts.separator "Shows rollout status, logs, resources, and health panels."
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(global_options:, command_options:, args:)
|
|
16
|
+
@global_options = global_options
|
|
17
|
+
@command_options = command_options
|
|
18
|
+
@args = args
|
|
19
|
+
@ui = Kdep::UI.new(color: false)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def execute
|
|
23
|
+
deploy_name = @args[0]
|
|
24
|
+
|
|
25
|
+
# Discover kdep/ directory
|
|
26
|
+
discovery = Kdep::Discovery.new
|
|
27
|
+
kdep_dir = discovery.find_kdep_dir
|
|
28
|
+
unless kdep_dir
|
|
29
|
+
@ui.error("No kdep/ directory found")
|
|
30
|
+
exit 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Resolve deploy directory
|
|
34
|
+
deploy_dir = resolve_deploy_dir(kdep_dir, deploy_name, discovery)
|
|
35
|
+
unless deploy_dir
|
|
36
|
+
exit 1
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Load config (nil env -- dashboard monitors live state)
|
|
40
|
+
config = Kdep::Config.new(deploy_dir, nil).load
|
|
41
|
+
|
|
42
|
+
# Validate context before any cluster operation
|
|
43
|
+
begin
|
|
44
|
+
Kdep::ContextGuard.new(config["context"]).validate!
|
|
45
|
+
rescue Kdep::Kubectl::Error => e
|
|
46
|
+
@ui.error(e.message)
|
|
47
|
+
exit 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Launch TUI dashboard
|
|
51
|
+
image = config["image"] || config["name"]
|
|
52
|
+
dashboard = Kdep::Dashboard.new(
|
|
53
|
+
"name" => config["name"],
|
|
54
|
+
"namespace" => config["namespace"] || "default",
|
|
55
|
+
"registry" => config["registry"],
|
|
56
|
+
"image" => image
|
|
57
|
+
)
|
|
58
|
+
dashboard.run
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def resolve_deploy_dir(kdep_dir, deploy_name, discovery)
|
|
64
|
+
if deploy_name
|
|
65
|
+
deploy_dir = File.join(kdep_dir, deploy_name)
|
|
66
|
+
unless File.directory?(deploy_dir)
|
|
67
|
+
@ui.error("Deploy target not found: #{deploy_name}")
|
|
68
|
+
deploys = discovery.find_deploys
|
|
69
|
+
if deploys.any?
|
|
70
|
+
@ui.info("Available deploys: #{deploys.join(', ')}")
|
|
71
|
+
end
|
|
72
|
+
return nil
|
|
73
|
+
end
|
|
74
|
+
deploy_dir
|
|
75
|
+
else
|
|
76
|
+
deploys = discovery.find_deploys
|
|
77
|
+
if deploys.length == 1
|
|
78
|
+
File.join(kdep_dir, deploys[0])
|
|
79
|
+
elsif deploys.length > 1
|
|
80
|
+
@ui.error("Multiple deploys found, specify one: #{deploys.join(', ')}")
|
|
81
|
+
nil
|
|
82
|
+
else
|
|
83
|
+
@ui.error("No deploy targets found in kdep/")
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
data/lib/kdep/commands/init.rb
CHANGED
|
@@ -86,6 +86,14 @@ module Kdep
|
|
|
86
86
|
)
|
|
87
87
|
@ui.file_written("kdep/#{deploy_name}/.gitignore")
|
|
88
88
|
|
|
89
|
+
if preset == "custom"
|
|
90
|
+
FileUtils.mkdir_p(File.join(target_dir, "presets"))
|
|
91
|
+
FileUtils.mkdir_p(File.join(target_dir, "resources"))
|
|
92
|
+
@ui.info("Created presets/ and resources/ directories for custom preset")
|
|
93
|
+
@ui.info("Add resource names to kdep/#{deploy_name}/presets/custom (one per line)")
|
|
94
|
+
@ui.info("Add matching .yml.erb templates to kdep/#{deploy_name}/resources/")
|
|
95
|
+
end
|
|
96
|
+
|
|
89
97
|
@ui.success("Initialized kdep/#{deploy_name} with #{preset} preset")
|
|
90
98
|
end
|
|
91
99
|
|
data/lib/kdep/commands/log.rb
CHANGED
|
@@ -42,8 +42,13 @@ module Kdep
|
|
|
42
42
|
# Load config
|
|
43
43
|
config = Kdep::Config.new(deploy_dir, nil).load
|
|
44
44
|
|
|
45
|
-
# Validate context
|
|
46
|
-
|
|
45
|
+
# Validate context before any cluster operation
|
|
46
|
+
begin
|
|
47
|
+
Kdep::ContextGuard.new(config["context"]).validate!
|
|
48
|
+
rescue Kdep::Kubectl::Error => e
|
|
49
|
+
@ui.error(e.message)
|
|
50
|
+
exit 1
|
|
51
|
+
end
|
|
47
52
|
|
|
48
53
|
# Find running pod
|
|
49
54
|
namespace = config["namespace"]
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
require "optparse"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
require "yaml"
|
|
4
|
+
|
|
5
|
+
module Kdep
|
|
6
|
+
module Commands
|
|
7
|
+
class Migrate
|
|
8
|
+
def self.option_parser
|
|
9
|
+
OptionParser.new do |opts|
|
|
10
|
+
opts.banner = "Usage: kdep migrate [path]"
|
|
11
|
+
opts.separator ""
|
|
12
|
+
opts.separator "Converts old deploy files (.app-name + app.yml) to kdep format."
|
|
13
|
+
opts.separator "Verifies byte-for-byte match between old materialized and new rendered output."
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize(global_options:, command_options:, args:)
|
|
18
|
+
@global_options = global_options
|
|
19
|
+
@command_options = command_options
|
|
20
|
+
@args = args
|
|
21
|
+
@ui = Kdep::UI.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def execute
|
|
25
|
+
path = @args[0]
|
|
26
|
+
unless path
|
|
27
|
+
@ui.error("Missing path argument")
|
|
28
|
+
@ui.info("Usage: kdep migrate [path]")
|
|
29
|
+
exit 1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
unless File.directory?(path)
|
|
33
|
+
@ui.error("Path not found: #{path}")
|
|
34
|
+
exit 1
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Parse old format
|
|
38
|
+
old = Kdep::OldFormat.new(path)
|
|
39
|
+
begin
|
|
40
|
+
name = old.app_name
|
|
41
|
+
kdep_config = old.to_kdep_config
|
|
42
|
+
rescue => e
|
|
43
|
+
@ui.error(e.message)
|
|
44
|
+
exit 1
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Create kdep/[name]/ directory with app.yml
|
|
48
|
+
target_dir = File.join(Dir.pwd, "kdep", name)
|
|
49
|
+
if File.exist?(target_dir)
|
|
50
|
+
@ui.error("kdep/#{name} already exists")
|
|
51
|
+
exit 1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
FileUtils.mkdir_p(target_dir)
|
|
55
|
+
File.write(File.join(target_dir, "app.yml"), YAML.dump(kdep_config))
|
|
56
|
+
@ui.file_written("kdep/#{name}/app.yml")
|
|
57
|
+
|
|
58
|
+
# Warn about secrets
|
|
59
|
+
@ui.warn("Secrets must be manually migrated to kdep/#{name}/secrets.yml")
|
|
60
|
+
|
|
61
|
+
# Render via existing pipeline
|
|
62
|
+
config = Kdep::Config.new(target_dir).load
|
|
63
|
+
preset = Kdep::Preset.new(config["preset"], target_dir)
|
|
64
|
+
resources = preset.resources
|
|
65
|
+
|
|
66
|
+
output_dir = File.join(Dir.pwd, ".rendered")
|
|
67
|
+
writer = Kdep::Writer.new(output_dir)
|
|
68
|
+
writer.clean
|
|
69
|
+
renderer = Kdep::Renderer.new(config, target_dir)
|
|
70
|
+
|
|
71
|
+
rendered_files = []
|
|
72
|
+
resources.each_with_index do |resource_name, idx|
|
|
73
|
+
content = renderer.render_resource(resource_name)
|
|
74
|
+
written_path = writer.write(resource_name, content, idx + 1)
|
|
75
|
+
rendered_files << written_path if written_path
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Compare byte-for-byte against old materialized files
|
|
79
|
+
old_files = old.materialized_files
|
|
80
|
+
if old_files.empty?
|
|
81
|
+
@ui.warn("No materialized files found to verify against")
|
|
82
|
+
@ui.success("Migration complete: kdep/#{name}/")
|
|
83
|
+
return
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
mismatches = compare_files(old_files, rendered_files)
|
|
87
|
+
|
|
88
|
+
if mismatches.empty?
|
|
89
|
+
@ui.success("Migration verified: #{rendered_files.length} files match byte-for-byte")
|
|
90
|
+
@ui.success("Migration complete: kdep/#{name}/")
|
|
91
|
+
else
|
|
92
|
+
@ui.error("Migration verification failed: #{mismatches.length} file(s) differ")
|
|
93
|
+
mismatches.each do |m|
|
|
94
|
+
@ui.error(" #{m[:file]}:")
|
|
95
|
+
m[:diff].each { |line| @ui.info(" #{line}") }
|
|
96
|
+
end
|
|
97
|
+
# Clean up failed migration
|
|
98
|
+
FileUtils.rm_rf(target_dir)
|
|
99
|
+
@ui.error("Migration aborted. Generated config removed.")
|
|
100
|
+
exit 1
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def compare_files(old_files, new_files)
|
|
107
|
+
mismatches = []
|
|
108
|
+
# Match by filename (basename)
|
|
109
|
+
old_by_name = {}
|
|
110
|
+
old_files.each { |f| old_by_name[File.basename(f)] = f }
|
|
111
|
+
|
|
112
|
+
new_by_name = {}
|
|
113
|
+
new_files.each { |f| new_by_name[File.basename(f)] = f }
|
|
114
|
+
|
|
115
|
+
# Check all old files have matching new files
|
|
116
|
+
old_by_name.each do |name, old_path|
|
|
117
|
+
new_path = new_by_name[name]
|
|
118
|
+
unless new_path
|
|
119
|
+
mismatches << { file: name, diff: ["- File exists in old but not in new rendered output"] }
|
|
120
|
+
next
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
old_content = File.read(old_path)
|
|
124
|
+
new_content = File.read(new_path)
|
|
125
|
+
|
|
126
|
+
if old_content != new_content
|
|
127
|
+
mismatches << { file: name, diff: generate_diff(old_content, new_content) }
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Check for new files not in old
|
|
132
|
+
new_by_name.each do |name, _|
|
|
133
|
+
unless old_by_name.key?(name)
|
|
134
|
+
mismatches << { file: name, diff: ["+ File exists in new but not in old materialized output"] }
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
mismatches
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def generate_diff(old_content, new_content)
|
|
142
|
+
old_lines = old_content.lines.map(&:chomp)
|
|
143
|
+
new_lines = new_content.lines.map(&:chomp)
|
|
144
|
+
diffs = []
|
|
145
|
+
max = [old_lines.length, new_lines.length].max
|
|
146
|
+
max.times do |i|
|
|
147
|
+
old_line = old_lines[i]
|
|
148
|
+
new_line = new_lines[i]
|
|
149
|
+
next if old_line == new_line
|
|
150
|
+
diffs << "- #{old_line}" if old_line
|
|
151
|
+
diffs << "+ #{new_line}" if new_line
|
|
152
|
+
end
|
|
153
|
+
diffs
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -45,8 +45,13 @@ module Kdep
|
|
|
45
45
|
# Load config
|
|
46
46
|
config = Kdep::Config.new(deploy_dir, nil).load
|
|
47
47
|
|
|
48
|
-
# Validate context
|
|
49
|
-
|
|
48
|
+
# Validate context before any cluster operation
|
|
49
|
+
begin
|
|
50
|
+
Kdep::ContextGuard.new(config["context"]).validate!
|
|
51
|
+
rescue Kdep::Kubectl::Error => e
|
|
52
|
+
@ui.error(e.message)
|
|
53
|
+
exit 1
|
|
54
|
+
end
|
|
50
55
|
|
|
51
56
|
namespace = config["namespace"]
|
|
52
57
|
app_name = config["name"]
|
data/lib/kdep/commands/scale.rb
CHANGED
|
@@ -49,8 +49,13 @@ module Kdep
|
|
|
49
49
|
# Load config
|
|
50
50
|
config = Kdep::Config.new(deploy_dir, nil).load
|
|
51
51
|
|
|
52
|
-
# Validate context
|
|
53
|
-
|
|
52
|
+
# Validate context before any cluster operation
|
|
53
|
+
begin
|
|
54
|
+
Kdep::ContextGuard.new(config["context"]).validate!
|
|
55
|
+
rescue Kdep::Kubectl::Error => e
|
|
56
|
+
@ui.error(e.message)
|
|
57
|
+
exit 1
|
|
58
|
+
end
|
|
54
59
|
|
|
55
60
|
namespace = config["namespace"]
|
|
56
61
|
app_name = config["name"]
|
|
@@ -64,8 +64,13 @@ module Kdep
|
|
|
64
64
|
# Load config
|
|
65
65
|
@config = Kdep::Config.new(deploy_dir, nil).load
|
|
66
66
|
|
|
67
|
-
# Validate context
|
|
68
|
-
|
|
67
|
+
# Validate context before any cluster operation
|
|
68
|
+
begin
|
|
69
|
+
Kdep::ContextGuard.new(@config["context"]).validate!
|
|
70
|
+
rescue Kdep::Kubectl::Error => e
|
|
71
|
+
@ui.error(e.message)
|
|
72
|
+
exit 1
|
|
73
|
+
end
|
|
69
74
|
|
|
70
75
|
@namespace = @config["namespace"]
|
|
71
76
|
|
data/lib/kdep/commands/sh.rb
CHANGED
|
@@ -40,8 +40,13 @@ module Kdep
|
|
|
40
40
|
# Load config
|
|
41
41
|
config = Kdep::Config.new(deploy_dir, nil).load
|
|
42
42
|
|
|
43
|
-
# Validate context
|
|
44
|
-
|
|
43
|
+
# Validate context before any cluster operation
|
|
44
|
+
begin
|
|
45
|
+
Kdep::ContextGuard.new(config["context"]).validate!
|
|
46
|
+
rescue Kdep::Kubectl::Error => e
|
|
47
|
+
@ui.error(e.message)
|
|
48
|
+
exit 1
|
|
49
|
+
end
|
|
45
50
|
|
|
46
51
|
# Find running pod
|
|
47
52
|
namespace = config["namespace"]
|
data/lib/kdep/commands/status.rb
CHANGED
|
@@ -39,8 +39,13 @@ module Kdep
|
|
|
39
39
|
# Load config
|
|
40
40
|
config = Kdep::Config.new(deploy_dir, nil).load
|
|
41
41
|
|
|
42
|
-
# Validate context
|
|
43
|
-
|
|
42
|
+
# Validate context before any cluster operation
|
|
43
|
+
begin
|
|
44
|
+
Kdep::ContextGuard.new(config["context"]).validate!
|
|
45
|
+
rescue Kdep::Kubectl::Error => e
|
|
46
|
+
@ui.error(e.message)
|
|
47
|
+
exit 1
|
|
48
|
+
end
|
|
44
49
|
|
|
45
50
|
# Get pods
|
|
46
51
|
namespace = config["namespace"]
|
|
@@ -65,12 +70,8 @@ module Kdep
|
|
|
65
70
|
@ui.info("Replicas: #{running}/#{total} ready")
|
|
66
71
|
|
|
67
72
|
# Cluster health check
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
health.report(@ui)
|
|
71
|
-
rescue NameError
|
|
72
|
-
# ClusterHealth not yet implemented, skip
|
|
73
|
-
end
|
|
73
|
+
health = Kdep::ClusterHealth.new
|
|
74
|
+
health.report(@ui)
|
|
74
75
|
end
|
|
75
76
|
|
|
76
77
|
private
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require "yaml"
|
|
2
|
+
|
|
3
|
+
module Kdep
|
|
4
|
+
class OldFormat
|
|
5
|
+
def initialize(path)
|
|
6
|
+
@path = path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def app_name
|
|
10
|
+
name_file = File.join(@path, ".app-name")
|
|
11
|
+
raise "Missing .app-name file in #{@path}" unless File.exist?(name_file)
|
|
12
|
+
File.read(name_file).strip
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def config
|
|
16
|
+
config_file = File.join(@path, "app.yml")
|
|
17
|
+
raise "Missing app.yml in #{@path}" unless File.exist?(config_file)
|
|
18
|
+
content = File.read(config_file)
|
|
19
|
+
if RUBY_VERSION >= "3.1"
|
|
20
|
+
YAML.safe_load(content, permitted_classes: [], permitted_symbols: [], aliases: false) || {}
|
|
21
|
+
else
|
|
22
|
+
YAML.safe_load(content, [], [], false) || {}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def materialized_files
|
|
27
|
+
mat_dir = materialized_dir
|
|
28
|
+
return [] unless mat_dir && File.directory?(mat_dir)
|
|
29
|
+
Dir.glob(File.join(mat_dir, "*.yml")).sort
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def materialized_dir
|
|
33
|
+
dir = File.join(@path, "materialized")
|
|
34
|
+
return dir if File.directory?(dir)
|
|
35
|
+
# Fallback to .rendered/ directory
|
|
36
|
+
dir = File.join(@path, ".rendered")
|
|
37
|
+
return dir if File.directory?(dir)
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def to_kdep_config
|
|
42
|
+
old = config
|
|
43
|
+
result = {}
|
|
44
|
+
%w[preset namespace name image registry context port replicas
|
|
45
|
+
command target env env_from resources probe domains
|
|
46
|
+
image_pull_secrets schedule].each do |key|
|
|
47
|
+
result[key] = old[key] if old.key?(key)
|
|
48
|
+
end
|
|
49
|
+
# Ensure name from .app-name if not in config
|
|
50
|
+
result["name"] ||= app_name
|
|
51
|
+
# Ensure image defaults to name
|
|
52
|
+
result["image"] ||= result["name"]
|
|
53
|
+
result
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/kdep/version.rb
CHANGED
data/lib/kdep.rb
CHANGED
|
@@ -8,6 +8,7 @@ require "kdep/template_context"
|
|
|
8
8
|
require "kdep/renderer"
|
|
9
9
|
require "kdep/validator"
|
|
10
10
|
require "kdep/writer"
|
|
11
|
+
require "kdep/old_format"
|
|
11
12
|
require "kdep/kubectl"
|
|
12
13
|
require "kdep/context_guard"
|
|
13
14
|
require "kdep/cluster_health"
|
|
@@ -28,6 +29,8 @@ require "kdep/commands/secrets"
|
|
|
28
29
|
require "kdep/commands/sh"
|
|
29
30
|
require "kdep/commands/restart"
|
|
30
31
|
require "kdep/commands/scale"
|
|
32
|
+
require "kdep/commands/migrate"
|
|
33
|
+
require "kdep/commands/dashboard"
|
|
31
34
|
require "kdep/dashboard/screen"
|
|
32
35
|
require "kdep/dashboard/layout"
|
|
33
36
|
require "kdep/dashboard/panel"
|
metadata
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kdep
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Leadfy
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '2.0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '2.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: minitest
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -68,10 +68,12 @@ files:
|
|
|
68
68
|
- lib/kdep/commands/apply.rb
|
|
69
69
|
- lib/kdep/commands/build.rb
|
|
70
70
|
- lib/kdep/commands/bump.rb
|
|
71
|
+
- lib/kdep/commands/dashboard.rb
|
|
71
72
|
- lib/kdep/commands/diff.rb
|
|
72
73
|
- lib/kdep/commands/eject.rb
|
|
73
74
|
- lib/kdep/commands/init.rb
|
|
74
75
|
- lib/kdep/commands/log.rb
|
|
76
|
+
- lib/kdep/commands/migrate.rb
|
|
75
77
|
- lib/kdep/commands/push.rb
|
|
76
78
|
- lib/kdep/commands/render.rb
|
|
77
79
|
- lib/kdep/commands/restart.rb
|
|
@@ -93,6 +95,7 @@ files:
|
|
|
93
95
|
- lib/kdep/discovery.rb
|
|
94
96
|
- lib/kdep/docker.rb
|
|
95
97
|
- lib/kdep/kubectl.rb
|
|
98
|
+
- lib/kdep/old_format.rb
|
|
96
99
|
- lib/kdep/preset.rb
|
|
97
100
|
- lib/kdep/registry.rb
|
|
98
101
|
- lib/kdep/renderer.rb
|
|
@@ -106,6 +109,7 @@ files:
|
|
|
106
109
|
- templates/init/gitignore
|
|
107
110
|
- templates/init/secrets.yml
|
|
108
111
|
- templates/presets/cronjob
|
|
112
|
+
- templates/presets/custom
|
|
109
113
|
- templates/presets/job
|
|
110
114
|
- templates/presets/web
|
|
111
115
|
- templates/presets/worker
|
|
@@ -120,7 +124,7 @@ homepage: https://github.com/repleadfy/kdep
|
|
|
120
124
|
licenses:
|
|
121
125
|
- MIT
|
|
122
126
|
metadata: {}
|
|
123
|
-
post_install_message:
|
|
127
|
+
post_install_message:
|
|
124
128
|
rdoc_options: []
|
|
125
129
|
require_paths:
|
|
126
130
|
- lib
|
|
@@ -135,8 +139,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
135
139
|
- !ruby/object:Gem::Version
|
|
136
140
|
version: '0'
|
|
137
141
|
requirements: []
|
|
138
|
-
rubygems_version: 3.
|
|
139
|
-
signing_key:
|
|
142
|
+
rubygems_version: 3.0.3.1
|
|
143
|
+
signing_key:
|
|
140
144
|
specification_version: 4
|
|
141
145
|
summary: Kubernetes deployment CLI
|
|
142
146
|
test_files: []
|