nvoi 0.1.8 → 0.2.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/Gemfile +1 -5
- data/Gemfile.lock +17 -8
- data/Rakefile +1 -1
- data/lib/nvoi/cli/config/command.rb +46 -41
- data/lib/nvoi/cli/credentials/edit/command.rb +20 -20
- data/lib/nvoi/cli/credentials/show/command.rb +1 -1
- data/lib/nvoi/cli/db/command.rb +10 -10
- data/lib/nvoi/cli/delete/command.rb +2 -2
- data/lib/nvoi/cli/deploy/command.rb +2 -2
- data/lib/nvoi/cli/deploy/steps/configure_tunnel.rb +2 -2
- data/lib/nvoi/cli/deploy/steps/provision_server.rb +1 -1
- data/lib/nvoi/cli/deploy/steps/provision_volume.rb +1 -1
- data/lib/nvoi/cli/exec/command.rb +3 -3
- data/lib/nvoi/cli/logs/command.rb +2 -2
- data/lib/nvoi/cli/onboard/command.rb +176 -622
- data/lib/nvoi/cli/onboard/steps/app.rb +108 -0
- data/lib/nvoi/cli/onboard/steps/app_name.rb +26 -0
- data/lib/nvoi/cli/onboard/steps/compute.rb +139 -0
- data/lib/nvoi/cli/onboard/steps/database.rb +97 -0
- data/lib/nvoi/cli/onboard/steps/domain.rb +48 -0
- data/lib/nvoi/cli/onboard/steps/env.rb +67 -0
- data/lib/nvoi/cli/onboard/ui.rb +84 -0
- data/lib/nvoi/cli/unlock/command.rb +2 -2
- data/lib/nvoi/cli.rb +0 -32
- data/lib/nvoi/configuration/app_service.rb +54 -0
- data/lib/nvoi/configuration/application.rb +44 -0
- data/lib/nvoi/configuration/builder.rb +417 -0
- data/lib/nvoi/configuration/database.rb +56 -0
- data/lib/nvoi/configuration/deploy.rb +15 -0
- data/lib/nvoi/{objects/service_spec.rb → configuration/deployment.rb} +4 -3
- data/lib/nvoi/{objects/config_override.rb → configuration/override.rb} +4 -4
- data/lib/nvoi/configuration/providers.rb +78 -0
- data/lib/nvoi/configuration/result.rb +43 -0
- data/lib/nvoi/configuration/root.rb +234 -0
- data/lib/nvoi/configuration/server.rb +39 -0
- data/lib/nvoi/configuration/service.rb +62 -0
- data/lib/nvoi/external/cloud/aws.rb +12 -12
- data/lib/nvoi/external/cloud/hetzner.rb +7 -7
- data/lib/nvoi/external/cloud/scaleway.rb +7 -7
- data/lib/nvoi/external/cloud/types.rb +42 -0
- data/lib/nvoi/external/database/mysql.rb +1 -1
- data/lib/nvoi/external/database/postgres.rb +1 -1
- data/lib/nvoi/external/database/provider.rb +1 -1
- data/lib/nvoi/external/database/sqlite.rb +1 -1
- data/lib/nvoi/external/database/types.rb +55 -0
- data/lib/nvoi/external/dns/cloudflare.rb +6 -6
- data/lib/nvoi/external/dns/types.rb +24 -0
- data/lib/nvoi/utils/config_loader.rb +12 -12
- data/lib/nvoi/utils/credential_store.rb +4 -4
- data/lib/nvoi/utils/env_resolver.rb +3 -3
- data/lib/nvoi/utils/namer.rb +2 -2
- data/lib/nvoi/utils/presence.rb +23 -0
- data/lib/nvoi/version.rb +1 -1
- data/lib/nvoi.rb +2 -17
- metadata +95 -58
- data/.claude/todo/refactor/00-overview.md +0 -171
- data/.claude/todo/refactor/01-objects.md +0 -96
- data/.claude/todo/refactor/02-utils.md +0 -143
- data/.claude/todo/refactor/03-external-cloud.md +0 -164
- data/.claude/todo/refactor/04-external-dns.md +0 -104
- data/.claude/todo/refactor/05-external.md +0 -133
- data/.claude/todo/refactor/06-cli.md +0 -123
- data/.claude/todo/refactor/07-cli-deploy-command.md +0 -177
- data/.claude/todo/refactor/08-cli-deploy-steps.md +0 -201
- data/.claude/todo/refactor/09-cli-delete-command.md +0 -169
- data/.claude/todo/refactor/10-cli-exec-command.md +0 -157
- data/.claude/todo/refactor/11-cli-credentials-command.md +0 -190
- data/.claude/todo/refactor/12-cli-db-command.md +0 -128
- data/.claude/todo/refactor/_target.md +0 -79
- data/.claude/todo/refactor-execution/00-entrypoint.md +0 -49
- data/.claude/todo/refactor-execution/01-objects.md +0 -42
- data/.claude/todo/refactor-execution/02-utils.md +0 -41
- data/.claude/todo/refactor-execution/03-external-cloud.md +0 -38
- data/.claude/todo/refactor-execution/04-external-dns.md +0 -35
- data/.claude/todo/refactor-execution/05-external-other.md +0 -46
- data/.claude/todo/refactor-execution/06-cli-deploy.md +0 -45
- data/.claude/todo/refactor-execution/07-cli-delete.md +0 -43
- data/.claude/todo/refactor-execution/08-cli-exec.md +0 -30
- data/.claude/todo/refactor-execution/09-cli-credentials.md +0 -34
- data/.claude/todo/refactor-execution/10-cli-db.md +0 -31
- data/.claude/todo/refactor-execution/11-cli-router.md +0 -44
- data/.claude/todo/refactor-execution/12-cleanup.md +0 -120
- data/.claude/todo/refactor-execution/_monitoring-strategy.md +0 -126
- data/.claude/todo/scaleway.impl.md +0 -644
- data/.claude/todo/scaleway.reference.md +0 -520
- data/.claude/todos/buckets.md +0 -41
- data/.claude/todos.md +0 -550
- data/ingest +0 -0
- data/lib/nvoi/config_api/actions/app.rb +0 -53
- data/lib/nvoi/config_api/actions/compute_provider.rb +0 -55
- data/lib/nvoi/config_api/actions/database.rb +0 -70
- data/lib/nvoi/config_api/actions/domain_provider.rb +0 -40
- data/lib/nvoi/config_api/actions/env.rb +0 -32
- data/lib/nvoi/config_api/actions/init.rb +0 -67
- data/lib/nvoi/config_api/actions/secret.rb +0 -32
- data/lib/nvoi/config_api/actions/server.rb +0 -66
- data/lib/nvoi/config_api/actions/service.rb +0 -52
- data/lib/nvoi/config_api/actions/volume.rb +0 -40
- data/lib/nvoi/config_api/base.rb +0 -38
- data/lib/nvoi/config_api/result.rb +0 -26
- data/lib/nvoi/config_api.rb +0 -93
- data/lib/nvoi/objects/configuration.rb +0 -483
- data/lib/nvoi/objects/database.rb +0 -56
- data/lib/nvoi/objects/dns.rb +0 -14
- data/lib/nvoi/objects/firewall.rb +0 -11
- data/lib/nvoi/objects/network.rb +0 -11
- data/lib/nvoi/objects/server.rb +0 -14
- data/lib/nvoi/objects/tunnel.rb +0 -14
- data/lib/nvoi/objects/volume.rb +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a77df0dc87230df49e67a6fe295594fd678626fe5c56bd1a13cbe3b83297784
|
|
4
|
+
data.tar.gz: ada2bac9b96a448105ecb9c48b1fede481a1bec883c4eadb01dd05a3f0edf64d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d30789748967c1dab8d0bc9069c135e476473168a5066018dc797c88e79cfc2f356cc1f64084cf3713b076c60f22b6d975098a3504534d3c14370129c923d55
|
|
7
|
+
data.tar.gz: cf31ca90acf5cf8a4c851a474d6efa9be23d0857571081b01b653bc631cceb9b2854b530c2ede54960262e5214a4f99f366a692fb6c2d71688dbc418f8fcb9a2
|
data/Gemfile
CHANGED
|
@@ -7,9 +7,5 @@ gemspec
|
|
|
7
7
|
group :development, :test do
|
|
8
8
|
gem "rubocop-rails-omakase", require: false
|
|
9
9
|
gem "simplecov", require: false
|
|
10
|
+
gem "minitest-reporters", require: false
|
|
10
11
|
end
|
|
11
|
-
|
|
12
|
-
gem "tty-prompt", "~> 0.23.1"
|
|
13
|
-
gem "tty-box", "~> 0.7.0"
|
|
14
|
-
gem "tty-spinner", "~> 0.9.3"
|
|
15
|
-
gem "tty-table", "~> 0.12.0"
|
data/Gemfile.lock
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
nvoi (0.
|
|
4
|
+
nvoi (0.2.0)
|
|
5
5
|
aws-sdk-ec2 (~> 1.400)
|
|
6
6
|
faraday (~> 2.7)
|
|
7
7
|
net-scp (~> 4.0)
|
|
8
8
|
net-ssh (~> 7.2)
|
|
9
|
+
pastel (~> 0.8)
|
|
9
10
|
thor (~> 1.3)
|
|
11
|
+
tty-box (~> 0.7)
|
|
12
|
+
tty-prompt (~> 0.23)
|
|
13
|
+
tty-spinner (~> 0.9)
|
|
14
|
+
tty-table (~> 0.12)
|
|
10
15
|
zeitwerk (~> 2.6)
|
|
11
16
|
|
|
12
17
|
GEM
|
|
@@ -27,9 +32,10 @@ GEM
|
|
|
27
32
|
uri (>= 0.13.1)
|
|
28
33
|
addressable (2.8.8)
|
|
29
34
|
public_suffix (>= 2.0.2, < 8.0)
|
|
35
|
+
ansi (1.5.0)
|
|
30
36
|
ast (2.4.3)
|
|
31
37
|
aws-eventstream (1.4.0)
|
|
32
|
-
aws-partitions (1.
|
|
38
|
+
aws-partitions (1.1194.0)
|
|
33
39
|
aws-sdk-core (3.239.2)
|
|
34
40
|
aws-eventstream (~> 1, >= 1.3.0)
|
|
35
41
|
aws-partitions (~> 1, >= 1.992.0)
|
|
@@ -45,6 +51,7 @@ GEM
|
|
|
45
51
|
aws-eventstream (~> 1, >= 1.0.2)
|
|
46
52
|
base64 (0.3.0)
|
|
47
53
|
bigdecimal (3.3.1)
|
|
54
|
+
builder (3.3.0)
|
|
48
55
|
concurrent-ruby (1.3.5)
|
|
49
56
|
connection_pool (3.0.2)
|
|
50
57
|
crack (1.0.1)
|
|
@@ -62,11 +69,16 @@ GEM
|
|
|
62
69
|
i18n (1.14.7)
|
|
63
70
|
concurrent-ruby (~> 1.0)
|
|
64
71
|
jmespath (1.6.2)
|
|
65
|
-
json (2.
|
|
72
|
+
json (2.18.0)
|
|
66
73
|
language_server-protocol (3.17.0.5)
|
|
67
74
|
lint_roller (1.1.0)
|
|
68
75
|
logger (1.7.0)
|
|
69
|
-
minitest (5.
|
|
76
|
+
minitest (5.27.0)
|
|
77
|
+
minitest-reporters (1.7.1)
|
|
78
|
+
ansi
|
|
79
|
+
builder
|
|
80
|
+
minitest (>= 5.0)
|
|
81
|
+
ruby-progressbar
|
|
70
82
|
net-http (0.8.0)
|
|
71
83
|
uri (>= 0.11.1)
|
|
72
84
|
net-scp (4.1.0)
|
|
@@ -177,15 +189,12 @@ PLATFORMS
|
|
|
177
189
|
DEPENDENCIES
|
|
178
190
|
bundler (~> 2.0)
|
|
179
191
|
minitest (~> 5.20)
|
|
192
|
+
minitest-reporters
|
|
180
193
|
nvoi!
|
|
181
194
|
rake (~> 13.0)
|
|
182
195
|
rubocop (~> 1.57)
|
|
183
196
|
rubocop-rails-omakase
|
|
184
197
|
simplecov
|
|
185
|
-
tty-box (~> 0.7.0)
|
|
186
|
-
tty-prompt (~> 0.23.1)
|
|
187
|
-
tty-spinner (~> 0.9.3)
|
|
188
|
-
tty-table (~> 0.12.0)
|
|
189
198
|
webmock (~> 3.19)
|
|
190
199
|
|
|
191
200
|
BUNDLED WITH
|
data/Rakefile
CHANGED
|
@@ -4,7 +4,7 @@ module Nvoi
|
|
|
4
4
|
class Cli
|
|
5
5
|
module Config
|
|
6
6
|
# Command helper for all config operations
|
|
7
|
-
# Uses CredentialStore for crypto,
|
|
7
|
+
# Uses CredentialStore for crypto, Configuration::Builder for transformations
|
|
8
8
|
class Command
|
|
9
9
|
def initialize(options)
|
|
10
10
|
@options = options
|
|
@@ -13,7 +13,7 @@ module Nvoi
|
|
|
13
13
|
|
|
14
14
|
# Initialize new config
|
|
15
15
|
def init(name, environment)
|
|
16
|
-
result =
|
|
16
|
+
result = Configuration::Builder.init(name:, environment:)
|
|
17
17
|
|
|
18
18
|
if result.failure?
|
|
19
19
|
error("Failed to initialize: #{result.error_message}")
|
|
@@ -40,118 +40,118 @@ module Nvoi
|
|
|
40
40
|
|
|
41
41
|
# Domain provider
|
|
42
42
|
def domain_set(provider, api_token:, account_id:)
|
|
43
|
-
with_config do |
|
|
44
|
-
|
|
43
|
+
with_config do |builder|
|
|
44
|
+
builder.domain_provider(provider, api_token:, account_id:)
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def domain_rm
|
|
49
|
-
with_config do |
|
|
50
|
-
|
|
49
|
+
with_config do |builder|
|
|
50
|
+
builder.remove_domain_provider
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Compute provider
|
|
55
55
|
def provider_set(provider, **opts)
|
|
56
|
-
with_config do |
|
|
57
|
-
|
|
56
|
+
with_config do |builder|
|
|
57
|
+
builder.compute_provider(provider, **opts)
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def provider_rm
|
|
62
|
-
with_config do |
|
|
63
|
-
|
|
62
|
+
with_config do |builder|
|
|
63
|
+
builder.remove_compute_provider
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# Server
|
|
68
68
|
def server_set(name, master: false, type: nil, location: nil, count: 1)
|
|
69
|
-
with_config do |
|
|
70
|
-
|
|
69
|
+
with_config do |builder|
|
|
70
|
+
builder.server(name, master:, type:, location:, count:)
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def server_rm(name)
|
|
75
|
-
with_config do |
|
|
76
|
-
|
|
75
|
+
with_config do |builder|
|
|
76
|
+
builder.remove_server(name)
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
# Volume
|
|
81
81
|
def volume_set(server, name, size: 10)
|
|
82
|
-
with_config do |
|
|
83
|
-
|
|
82
|
+
with_config do |builder|
|
|
83
|
+
builder.volume(server, name, size:)
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def volume_rm(server, name)
|
|
88
|
-
with_config do |
|
|
89
|
-
|
|
88
|
+
with_config do |builder|
|
|
89
|
+
builder.remove_volume(server, name)
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
# App
|
|
94
94
|
def app_set(name, servers:, **opts)
|
|
95
|
-
with_config do |
|
|
96
|
-
|
|
95
|
+
with_config do |builder|
|
|
96
|
+
builder.app_entry(name, servers:, **opts)
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def app_rm(name)
|
|
101
|
-
with_config do |
|
|
102
|
-
|
|
101
|
+
with_config do |builder|
|
|
102
|
+
builder.remove_app(name)
|
|
103
103
|
end
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
# Database
|
|
107
107
|
def database_set(servers:, adapter:, **opts)
|
|
108
|
-
with_config do |
|
|
109
|
-
|
|
108
|
+
with_config do |builder|
|
|
109
|
+
builder.database(servers:, adapter:, **opts)
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
def database_rm
|
|
114
|
-
with_config do |
|
|
115
|
-
|
|
114
|
+
with_config do |builder|
|
|
115
|
+
builder.remove_database
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
# Service
|
|
120
120
|
def service_set(name, servers:, image:, **opts)
|
|
121
|
-
with_config do |
|
|
122
|
-
|
|
121
|
+
with_config do |builder|
|
|
122
|
+
builder.service(name, servers:, image:, **opts)
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
def service_rm(name)
|
|
127
|
-
with_config do |
|
|
128
|
-
|
|
127
|
+
with_config do |builder|
|
|
128
|
+
builder.remove_service(name)
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
# Secret
|
|
133
133
|
def secret_set(key_name, value)
|
|
134
|
-
with_config do |
|
|
135
|
-
|
|
134
|
+
with_config do |builder|
|
|
135
|
+
builder.secret(key_name, value)
|
|
136
136
|
end
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def secret_rm(key_name)
|
|
140
|
-
with_config do |
|
|
141
|
-
|
|
140
|
+
with_config do |builder|
|
|
141
|
+
builder.remove_secret(key_name)
|
|
142
142
|
end
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
# Env
|
|
146
146
|
def env_set(key_name, value)
|
|
147
|
-
with_config do |
|
|
148
|
-
|
|
147
|
+
with_config do |builder|
|
|
148
|
+
builder.env(key_name, value)
|
|
149
149
|
end
|
|
150
150
|
end
|
|
151
151
|
|
|
152
152
|
def env_rm(key_name)
|
|
153
|
-
with_config do |
|
|
154
|
-
|
|
153
|
+
with_config do |builder|
|
|
154
|
+
builder.remove_env(key_name)
|
|
155
155
|
end
|
|
156
156
|
end
|
|
157
157
|
|
|
@@ -174,20 +174,25 @@ module Nvoi
|
|
|
174
174
|
yaml = store.read
|
|
175
175
|
data = YAML.safe_load(yaml, permitted_classes: [Symbol])
|
|
176
176
|
|
|
177
|
-
# Transform
|
|
178
|
-
|
|
177
|
+
# Transform using Builder
|
|
178
|
+
builder = Configuration::Builder.from_hash(data)
|
|
179
|
+
result = yield(builder)
|
|
179
180
|
|
|
180
181
|
if result.failure?
|
|
181
182
|
error("#{result.error_type}: #{result.error_message}")
|
|
182
183
|
else
|
|
183
184
|
# Serialize and write
|
|
184
|
-
store.write(
|
|
185
|
+
store.write(builder.to_yaml)
|
|
185
186
|
success("Config updated")
|
|
186
187
|
end
|
|
187
188
|
rescue Errors::CredentialError => e
|
|
188
189
|
error(e.message)
|
|
189
190
|
rescue Errors::DecryptionError => e
|
|
190
191
|
error("Decryption failed: #{e.message}")
|
|
192
|
+
rescue ArgumentError => e
|
|
193
|
+
error("invalid_args: #{e.message}")
|
|
194
|
+
rescue Errors::ConfigValidationError => e
|
|
195
|
+
error("validation_error: #{e.message}")
|
|
191
196
|
end
|
|
192
197
|
|
|
193
198
|
def update_gitignore
|
|
@@ -151,7 +151,7 @@ module Nvoi
|
|
|
151
151
|
|
|
152
152
|
def resolve_working_dir
|
|
153
153
|
wd = @options[:dir]
|
|
154
|
-
if wd.
|
|
154
|
+
if wd.blank? || wd == "."
|
|
155
155
|
Dir.pwd
|
|
156
156
|
else
|
|
157
157
|
File.expand_path(wd)
|
|
@@ -160,7 +160,7 @@ module Nvoi
|
|
|
160
160
|
|
|
161
161
|
def resolve_enc_path(working_dir)
|
|
162
162
|
enc_path = @options[:credentials]
|
|
163
|
-
return File.join(working_dir, DEFAULT_ENCRYPTED_FILE) if enc_path.
|
|
163
|
+
return File.join(working_dir, DEFAULT_ENCRYPTED_FILE) if enc_path.blank?
|
|
164
164
|
|
|
165
165
|
enc_path
|
|
166
166
|
end
|
|
@@ -184,18 +184,18 @@ module Nvoi
|
|
|
184
184
|
return "application section is required" unless app.is_a?(Hash)
|
|
185
185
|
|
|
186
186
|
# Application name
|
|
187
|
-
return "application.name is required" if app["name"].
|
|
187
|
+
return "application.name is required" if app["name"].blank?
|
|
188
188
|
|
|
189
189
|
# Environment
|
|
190
|
-
return "application.environment is required" if app["environment"].
|
|
190
|
+
return "application.environment is required" if app["environment"].blank?
|
|
191
191
|
|
|
192
192
|
# Domain provider
|
|
193
193
|
domain_provider = app["domain_provider"]
|
|
194
194
|
return "application.domain_provider.cloudflare is required" unless domain_provider&.dig("cloudflare")
|
|
195
195
|
|
|
196
196
|
cf = domain_provider["cloudflare"]
|
|
197
|
-
return "application.domain_provider.cloudflare.api_token is required" if cf["api_token"].
|
|
198
|
-
return "application.domain_provider.cloudflare.account_id is required" if cf["account_id"].
|
|
197
|
+
return "application.domain_provider.cloudflare.api_token is required" if cf["api_token"].blank?
|
|
198
|
+
return "application.domain_provider.cloudflare.account_id is required" if cf["account_id"].blank?
|
|
199
199
|
|
|
200
200
|
# Compute provider
|
|
201
201
|
compute_provider = app["compute_provider"]
|
|
@@ -203,22 +203,22 @@ module Nvoi
|
|
|
203
203
|
return "compute_provider (hetzner, aws, or scaleway) is required" unless has_compute
|
|
204
204
|
|
|
205
205
|
if (h = compute_provider&.dig("hetzner"))
|
|
206
|
-
return "application.compute_provider.hetzner.api_token is required" if h["api_token"].
|
|
207
|
-
return "application.compute_provider.hetzner.server_type is required" if h["server_type"].
|
|
208
|
-
return "application.compute_provider.hetzner.server_location is required" if h["server_location"].
|
|
206
|
+
return "application.compute_provider.hetzner.api_token is required" if h["api_token"].blank?
|
|
207
|
+
return "application.compute_provider.hetzner.server_type is required" if h["server_type"].blank?
|
|
208
|
+
return "application.compute_provider.hetzner.server_location is required" if h["server_location"].blank?
|
|
209
209
|
end
|
|
210
210
|
|
|
211
211
|
if (a = compute_provider&.dig("aws"))
|
|
212
|
-
return "application.compute_provider.aws.access_key_id is required" if a["access_key_id"].
|
|
213
|
-
return "application.compute_provider.aws.secret_access_key is required" if a["secret_access_key"].
|
|
214
|
-
return "application.compute_provider.aws.region is required" if a["region"].
|
|
215
|
-
return "application.compute_provider.aws.instance_type is required" if a["instance_type"].
|
|
212
|
+
return "application.compute_provider.aws.access_key_id is required" if a["access_key_id"].blank?
|
|
213
|
+
return "application.compute_provider.aws.secret_access_key is required" if a["secret_access_key"].blank?
|
|
214
|
+
return "application.compute_provider.aws.region is required" if a["region"].blank?
|
|
215
|
+
return "application.compute_provider.aws.instance_type is required" if a["instance_type"].blank?
|
|
216
216
|
end
|
|
217
217
|
|
|
218
218
|
if (s = compute_provider&.dig("scaleway"))
|
|
219
|
-
return "application.compute_provider.scaleway.secret_key is required" if s["secret_key"].
|
|
220
|
-
return "application.compute_provider.scaleway.project_id is required" if s["project_id"].
|
|
221
|
-
return "application.compute_provider.scaleway.server_type is required" if s["server_type"].
|
|
219
|
+
return "application.compute_provider.scaleway.secret_key is required" if s["secret_key"].blank?
|
|
220
|
+
return "application.compute_provider.scaleway.project_id is required" if s["project_id"].blank?
|
|
221
|
+
return "application.compute_provider.scaleway.server_type is required" if s["server_type"].blank?
|
|
222
222
|
end
|
|
223
223
|
|
|
224
224
|
# Servers (if any services defined)
|
|
@@ -236,7 +236,7 @@ module Nvoi
|
|
|
236
236
|
app_services.each do |service_name, svc|
|
|
237
237
|
next unless svc
|
|
238
238
|
|
|
239
|
-
return "app.#{service_name}.servers is required" if svc["servers"].
|
|
239
|
+
return "app.#{service_name}.servers is required" if svc["servers"].to_a.empty?
|
|
240
240
|
|
|
241
241
|
svc["servers"].each do |ref|
|
|
242
242
|
return "app.#{service_name} references undefined server: #{ref}" unless defined_servers.include?(ref)
|
|
@@ -245,7 +245,7 @@ module Nvoi
|
|
|
245
245
|
|
|
246
246
|
# Validate database
|
|
247
247
|
if database
|
|
248
|
-
return "database.servers is required" if database["servers"].
|
|
248
|
+
return "database.servers is required" if database["servers"].to_a.empty?
|
|
249
249
|
|
|
250
250
|
database["servers"].each do |ref|
|
|
251
251
|
return "database references undefined server: #{ref}" unless defined_servers.include?(ref)
|
|
@@ -268,10 +268,10 @@ module Nvoi
|
|
|
268
268
|
adapter = db["adapter"]&.downcase
|
|
269
269
|
url = db["url"]
|
|
270
270
|
|
|
271
|
-
return "database.adapter is required" if adapter.
|
|
271
|
+
return "database.adapter is required" if adapter.blank?
|
|
272
272
|
|
|
273
273
|
# URL takes precedence - if provided, no secrets needed
|
|
274
|
-
has_url =
|
|
274
|
+
has_url = !url.blank?
|
|
275
275
|
|
|
276
276
|
case adapter
|
|
277
277
|
when "postgres", "postgresql"
|
data/lib/nvoi/cli/db/command.rb
CHANGED
|
@@ -60,7 +60,7 @@ module Nvoi
|
|
|
60
60
|
result = ssh.execute("test -f #{metadata_file} && cat #{metadata_file} || echo '{}'")
|
|
61
61
|
|
|
62
62
|
begin
|
|
63
|
-
metadata =
|
|
63
|
+
metadata = External::Database::Types::BranchMetadata.from_json(result)
|
|
64
64
|
branches = metadata.branches
|
|
65
65
|
rescue JSON::ParserError
|
|
66
66
|
branches = []
|
|
@@ -185,9 +185,9 @@ module Nvoi
|
|
|
185
185
|
|
|
186
186
|
def apply_branch_override
|
|
187
187
|
branch = @options[:branch]
|
|
188
|
-
return if branch.
|
|
188
|
+
return if branch.blank?
|
|
189
189
|
|
|
190
|
-
override =
|
|
190
|
+
override = Configuration::Override.new(branch:)
|
|
191
191
|
override.apply(@config)
|
|
192
192
|
end
|
|
193
193
|
|
|
@@ -204,12 +204,12 @@ module Nvoi
|
|
|
204
204
|
|
|
205
205
|
def build_dump_options
|
|
206
206
|
if @db_provider.is_a?(External::Database::Sqlite)
|
|
207
|
-
|
|
207
|
+
External::Database::Types::DumpOptions.new(
|
|
208
208
|
host_path: @creds.host_path,
|
|
209
209
|
database: @creds.database
|
|
210
210
|
)
|
|
211
211
|
else
|
|
212
|
-
|
|
212
|
+
External::Database::Types::DumpOptions.new(
|
|
213
213
|
pod_name: @config.namer.database_pod_name,
|
|
214
214
|
database: @creds.database,
|
|
215
215
|
user: @creds.user,
|
|
@@ -222,12 +222,12 @@ module Nvoi
|
|
|
222
222
|
sanitized_name = sanitize_db_name(new_db_name)
|
|
223
223
|
|
|
224
224
|
if @db_provider.is_a?(External::Database::Sqlite)
|
|
225
|
-
|
|
225
|
+
External::Database::Types::RestoreOptions.new(
|
|
226
226
|
host_path: @creds.host_path,
|
|
227
227
|
database: sanitized_name
|
|
228
228
|
)
|
|
229
229
|
else
|
|
230
|
-
|
|
230
|
+
External::Database::Types::RestoreOptions.new(
|
|
231
231
|
pod_name: @config.namer.database_pod_name,
|
|
232
232
|
database: sanitized_name,
|
|
233
233
|
user: @creds.user,
|
|
@@ -255,12 +255,12 @@ module Nvoi
|
|
|
255
255
|
result = ssh.execute("test -f #{metadata_file} && cat #{metadata_file} || echo '{}'")
|
|
256
256
|
|
|
257
257
|
metadata = begin
|
|
258
|
-
|
|
258
|
+
External::Database::Types::BranchMetadata.from_json(result)
|
|
259
259
|
rescue JSON::ParserError
|
|
260
|
-
|
|
260
|
+
External::Database::Types::BranchMetadata.new
|
|
261
261
|
end
|
|
262
262
|
|
|
263
|
-
metadata.branches <<
|
|
263
|
+
metadata.branches << External::Database::Types::Branch.new(
|
|
264
264
|
id: branch_id,
|
|
265
265
|
created_at: Time.now.iso8601,
|
|
266
266
|
size:,
|
|
@@ -64,9 +64,9 @@ module Nvoi
|
|
|
64
64
|
|
|
65
65
|
def apply_branch_override
|
|
66
66
|
branch = @options[:branch]
|
|
67
|
-
return if branch.
|
|
67
|
+
return if branch.blank?
|
|
68
68
|
|
|
69
|
-
override =
|
|
69
|
+
override = Configuration::Override.new(branch:)
|
|
70
70
|
override.apply(@config)
|
|
71
71
|
end
|
|
72
72
|
end
|
|
@@ -65,9 +65,9 @@ module Nvoi
|
|
|
65
65
|
|
|
66
66
|
def apply_branch_override
|
|
67
67
|
branch = @options[:branch]
|
|
68
|
-
return if branch.
|
|
68
|
+
return if branch.blank?
|
|
69
69
|
|
|
70
|
-
override =
|
|
70
|
+
override = Configuration::Override.new(branch:)
|
|
71
71
|
override.apply(@config)
|
|
72
72
|
end
|
|
73
73
|
|
|
@@ -43,7 +43,7 @@ module Nvoi
|
|
|
43
43
|
|
|
44
44
|
tunnel = setup_tunnel(tunnel_name, hostnames, service_url, service_config.domain)
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
External::Dns::Types::Tunnel::Info.new(
|
|
47
47
|
service_name:,
|
|
48
48
|
hostname: primary_hostname,
|
|
49
49
|
tunnel_id: tunnel.tunnel_id,
|
|
@@ -90,7 +90,7 @@ module Nvoi
|
|
|
90
90
|
|
|
91
91
|
@log.success "Tunnel configured: %s", tunnel_name
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
External::Dns::Types::Tunnel::Info.new(
|
|
94
94
|
tunnel_id: tunnel.id,
|
|
95
95
|
tunnel_token: token
|
|
96
96
|
)
|
|
@@ -66,7 +66,7 @@ module Nvoi
|
|
|
66
66
|
raise Errors::VolumeError, "server not found: #{vol_config[:server_name]}" unless server
|
|
67
67
|
|
|
68
68
|
# Create volume
|
|
69
|
-
opts =
|
|
69
|
+
opts = External::Cloud::Types::Volume::CreateOptions.new(
|
|
70
70
|
name: vol_config[:name],
|
|
71
71
|
size: vol_config[:size],
|
|
72
72
|
server_id: server.id
|
|
@@ -55,9 +55,9 @@ module Nvoi
|
|
|
55
55
|
|
|
56
56
|
def apply_branch_override
|
|
57
57
|
branch = @options[:branch]
|
|
58
|
-
return if branch.
|
|
58
|
+
return if branch.blank?
|
|
59
59
|
|
|
60
|
-
override =
|
|
60
|
+
override = Configuration::Override.new(branch:)
|
|
61
61
|
override.apply(@config)
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -132,7 +132,7 @@ module Nvoi
|
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
def resolve_server_name(name)
|
|
135
|
-
return @config.server_name if name.
|
|
135
|
+
return @config.server_name if name.blank? || name == "main"
|
|
136
136
|
|
|
137
137
|
parts = name.split("-")
|
|
138
138
|
if parts.length >= 2
|
|
@@ -55,9 +55,9 @@ module Nvoi
|
|
|
55
55
|
|
|
56
56
|
def apply_branch_override
|
|
57
57
|
branch = @options[:branch]
|
|
58
|
-
return if branch.
|
|
58
|
+
return if branch.blank?
|
|
59
59
|
|
|
60
|
-
override =
|
|
60
|
+
override = Configuration::Override.new(branch:)
|
|
61
61
|
override.apply(@config)
|
|
62
62
|
end
|
|
63
63
|
end
|