belt 0.2.7 → 0.2.8
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/belt/cli/backup_config.rb +4 -89
- data/lib/belt/cli/console_command.rb +9 -0
- data/lib/belt/cli/deploy_command.rb +21 -1
- data/lib/belt/cli/environment_config.rb +131 -0
- data/lib/belt/cli/tables_command.rb +3 -3
- data/lib/belt/cli/terraform_command.rb +8 -0
- data/lib/belt/helpers/cors_origin.rb +1 -1
- data/lib/belt/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5ad9e95cd921b5bf91ffd28544086a895e49ce04a59e4a6b62d64cb9b1ec7bd1
|
|
4
|
+
data.tar.gz: 7e8795bcfc4e7941f5bd6b426a509ada6dd8d931c39b2af777e0725e8a78e021
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d228ac8ae6a440aa17c56b5ab16e48ebda349666b5b22d08456d5c99df4a66f47461031d48d049f81cd8c9d6253d9aa410e8ffa25a45998296ec5c3af524a651
|
|
7
|
+
data.tar.gz: 943b4993668f4c3be7ede7ff7dda63f7e4682906af122632fba1fe3ef66b257ee3970d93383dfe7fbd8df1d88a4852f1cbdaca37f2beac8db26ad0c995d75230
|
|
@@ -7,17 +7,11 @@ module Belt
|
|
|
7
7
|
|
|
8
8
|
# Load backup config from infrastructure/<env>/belt.rb
|
|
9
9
|
# Returns nil if no config file exists or backups aren't configured
|
|
10
|
+
# NOTE: Prefer EnvironmentConfig.load which loads the full config including backups.
|
|
11
|
+
# This method is kept for backward compatibility.
|
|
10
12
|
def self.load(env, infra_dir: nil)
|
|
11
|
-
infra_dir
|
|
12
|
-
|
|
13
|
-
return nil unless File.exist?(config_file)
|
|
14
|
-
|
|
15
|
-
config = new
|
|
16
|
-
evaluator = ConfigEvaluator.new(config)
|
|
17
|
-
evaluator.evaluate(File.read(config_file), config_file)
|
|
18
|
-
|
|
19
|
-
# Return nil if no backups were configured
|
|
20
|
-
config.any? ? config : nil
|
|
13
|
+
env_config = EnvironmentConfig.load(env, infra_dir: infra_dir)
|
|
14
|
+
env_config.backups? ? env_config.backup_config : nil
|
|
21
15
|
end
|
|
22
16
|
|
|
23
17
|
def initialize
|
|
@@ -38,85 +32,6 @@ module Belt
|
|
|
38
32
|
def any?
|
|
39
33
|
dynamodb? || cognito? || @s3_buckets.any?
|
|
40
34
|
end
|
|
41
|
-
|
|
42
|
-
# Evaluates the belt.rb config file in an isolated context
|
|
43
|
-
# that intercepts Belt.configure calls
|
|
44
|
-
class ConfigEvaluator
|
|
45
|
-
def initialize(config)
|
|
46
|
-
@config = config
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def evaluate(content, filename)
|
|
50
|
-
# The config file calls Belt.configure { |config| ... }
|
|
51
|
-
# We wrap the content to intercept the Belt constant lookup
|
|
52
|
-
# by evaluating in a module where Belt is redefined
|
|
53
|
-
config = @config
|
|
54
|
-
sandbox = Module.new
|
|
55
|
-
# Define a Belt module inside the sandbox that has .configure
|
|
56
|
-
belt_proxy = Module.new do
|
|
57
|
-
define_singleton_method(:configure) do |&block|
|
|
58
|
-
block.call(ConfigDSL.new(config))
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
sandbox.const_set(:Belt, belt_proxy)
|
|
62
|
-
|
|
63
|
-
# Evaluate the file content within the sandbox module
|
|
64
|
-
sandbox.module_eval(content, filename)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# DSL yielded to the block inside Belt.configure { |config| ... }
|
|
69
|
-
class ConfigDSL
|
|
70
|
-
def initialize(config)
|
|
71
|
-
@config = config
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def backups(enabled = nil, &block)
|
|
75
|
-
if enabled == true
|
|
76
|
-
# Simple mode: config.backups = true → just DynamoDB for all tables
|
|
77
|
-
@config.instance_variable_set(:@dynamodb_tables, :all)
|
|
78
|
-
elsif block
|
|
79
|
-
backup_dsl = BackupDSL.new(@config)
|
|
80
|
-
backup_dsl.instance_eval(&block)
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# DSL for the backups block
|
|
86
|
-
class BackupDSL
|
|
87
|
-
def initialize(config)
|
|
88
|
-
@config = config
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def dynamodb(scope = :all)
|
|
92
|
-
if scope == :all
|
|
93
|
-
@config.instance_variable_set(:@dynamodb_tables, :all)
|
|
94
|
-
else
|
|
95
|
-
tables = Array(scope)
|
|
96
|
-
@config.instance_variable_set(:@dynamodb_tables, tables.map(&:to_s))
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def cognito(*exports)
|
|
101
|
-
@config.instance_variable_set(:@cognito_exports, exports.flatten.map(&:to_sym))
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def s3(*buckets)
|
|
105
|
-
@config.instance_variable_set(:@s3_buckets, buckets.flatten.map(&:to_sym))
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def retention(opts = {})
|
|
109
|
-
current = @config.instance_variable_get(:@retention)
|
|
110
|
-
merged = current.merge(opts.transform_keys(&:to_sym))
|
|
111
|
-
|
|
112
|
-
# Convert duration objects (90.days) to integer days
|
|
113
|
-
merged.transform_values! do |v|
|
|
114
|
-
v.respond_to?(:to_i) ? v.to_i : v
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
@config.instance_variable_set(:@retention, merged)
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
35
|
end
|
|
121
36
|
end
|
|
122
37
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'optparse'
|
|
4
|
+
require_relative 'environment_config'
|
|
4
5
|
|
|
5
6
|
module Belt
|
|
6
7
|
module CLI
|
|
@@ -25,6 +26,8 @@ module Belt
|
|
|
25
26
|
@environment = @args.first || ENV['BELT_ENV'] || 'dev'
|
|
26
27
|
ENV['ENVIRONMENT'] = @environment
|
|
27
28
|
|
|
29
|
+
apply_env_config!
|
|
30
|
+
|
|
28
31
|
if @options[:run]
|
|
29
32
|
exec_runner(@options[:run])
|
|
30
33
|
else
|
|
@@ -45,6 +48,12 @@ module Belt
|
|
|
45
48
|
end.parse!(@args)
|
|
46
49
|
end
|
|
47
50
|
|
|
51
|
+
def apply_env_config!
|
|
52
|
+
env_config = EnvironmentConfig.load(@environment)
|
|
53
|
+
env_config.apply!
|
|
54
|
+
puts " 🔑 Using AWS profile: #{env_config.aws_profile}" if env_config.aws_profile?
|
|
55
|
+
end
|
|
56
|
+
|
|
48
57
|
def exec_console
|
|
49
58
|
production_guard!
|
|
50
59
|
boot_app
|
|
@@ -8,6 +8,7 @@ require_relative 'env_resolver'
|
|
|
8
8
|
require_relative 'terraform_command'
|
|
9
9
|
require_relative 'backup_config'
|
|
10
10
|
require_relative 'backup_runner'
|
|
11
|
+
require_relative 'environment_config'
|
|
11
12
|
|
|
12
13
|
module Belt
|
|
13
14
|
module CLI
|
|
@@ -144,6 +145,8 @@ module Belt
|
|
|
144
145
|
validate!
|
|
145
146
|
env_dir = File.join(@infra_dir, @env)
|
|
146
147
|
|
|
148
|
+
load_and_apply_env_config!
|
|
149
|
+
|
|
147
150
|
puts "belt → deploying #{@env} (in #{env_dir}/)\n\n"
|
|
148
151
|
|
|
149
152
|
ensure_lockfile_consistent!
|
|
@@ -168,6 +171,7 @@ module Belt
|
|
|
168
171
|
|
|
169
172
|
def run_backup_only
|
|
170
173
|
validate!
|
|
174
|
+
load_and_apply_env_config!
|
|
171
175
|
|
|
172
176
|
puts "belt → running backups for #{@env}\n\n"
|
|
173
177
|
|
|
@@ -190,6 +194,7 @@ module Belt
|
|
|
190
194
|
|
|
191
195
|
def run_rebuild
|
|
192
196
|
validate!
|
|
197
|
+
load_and_apply_env_config!
|
|
193
198
|
validate_aws!
|
|
194
199
|
|
|
195
200
|
puts "belt → rebuilding Lambda for #{@env}\n\n"
|
|
@@ -207,6 +212,21 @@ module Belt
|
|
|
207
212
|
|
|
208
213
|
private
|
|
209
214
|
|
|
215
|
+
def load_and_apply_env_config!
|
|
216
|
+
@env_config = EnvironmentConfig.load(@env, infra_dir: @infra_dir)
|
|
217
|
+
@env_config.apply!
|
|
218
|
+
print_env_config_info
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def print_env_config_info
|
|
222
|
+
puts " 🔑 Using AWS profile: #{@env_config.aws_profile}" if @env_config.aws_profile?
|
|
223
|
+
return unless @env_config.env_vars?
|
|
224
|
+
|
|
225
|
+
@env_config.env_vars.each_key do |key|
|
|
226
|
+
puts " 📌 Setting #{key}"
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
210
230
|
def find_project_root
|
|
211
231
|
# Walk up from infra dir to find project root (where Gemfile lives)
|
|
212
232
|
dir = @infra_dir ? File.dirname(@infra_dir) : Dir.pwd
|
|
@@ -264,7 +284,7 @@ module Belt
|
|
|
264
284
|
end
|
|
265
285
|
|
|
266
286
|
def load_backup_config
|
|
267
|
-
|
|
287
|
+
@env_config.backups? ? @env_config.backup_config : nil
|
|
268
288
|
end
|
|
269
289
|
|
|
270
290
|
def run_backup_phase(backup_config)
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Belt
|
|
4
|
+
module CLI
|
|
5
|
+
class EnvironmentConfig
|
|
6
|
+
attr_reader :aws_profile, :env_vars, :backup_config
|
|
7
|
+
|
|
8
|
+
# Load environment config from infrastructure/<env>/belt.rb
|
|
9
|
+
# Returns an EnvironmentConfig instance (never nil — unconfigured is valid)
|
|
10
|
+
def self.load(env, infra_dir: nil)
|
|
11
|
+
infra_dir ||= 'infrastructure'
|
|
12
|
+
config_file = File.join(infra_dir, env, 'belt.rb')
|
|
13
|
+
|
|
14
|
+
config = new
|
|
15
|
+
return config unless File.exist?(config_file)
|
|
16
|
+
|
|
17
|
+
evaluator = ConfigEvaluator.new(config)
|
|
18
|
+
evaluator.evaluate(File.read(config_file), config_file)
|
|
19
|
+
config
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize
|
|
23
|
+
@aws_profile = nil
|
|
24
|
+
@env_vars = {}
|
|
25
|
+
@backup_config = BackupConfig.new
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def aws_profile?
|
|
29
|
+
!@aws_profile.nil? && !@aws_profile.empty?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def env_vars?
|
|
33
|
+
@env_vars.any?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def backups?
|
|
37
|
+
@backup_config.any?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Apply the configured aws_profile and env vars to the current process.
|
|
41
|
+
# Call this before running terraform, aws cli, etc.
|
|
42
|
+
def apply!
|
|
43
|
+
ENV['AWS_PROFILE'] = @aws_profile if aws_profile?
|
|
44
|
+
@env_vars.each { |key, value| ENV[key] = value }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class ConfigEvaluator
|
|
48
|
+
def initialize(config)
|
|
49
|
+
@config = config
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def evaluate(content, filename)
|
|
53
|
+
config = @config
|
|
54
|
+
sandbox = Module.new
|
|
55
|
+
belt_proxy = Module.new do
|
|
56
|
+
define_singleton_method(:configure) do |&block|
|
|
57
|
+
block.call(ConfigDSL.new(config))
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
sandbox.const_set(:Belt, belt_proxy)
|
|
61
|
+
sandbox.module_eval(content, filename)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class ConfigDSL
|
|
66
|
+
def initialize(config)
|
|
67
|
+
@config = config
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def aws_profile=(profile)
|
|
71
|
+
@config.instance_variable_set(:@aws_profile, profile.to_s)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def env(&)
|
|
75
|
+
env_dsl = EnvDSL.new(@config)
|
|
76
|
+
env_dsl.instance_eval(&)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def backups(enabled = nil, &block)
|
|
80
|
+
if enabled == true
|
|
81
|
+
@config.backup_config.instance_variable_set(:@dynamodb_tables, :all)
|
|
82
|
+
elsif block
|
|
83
|
+
backup_dsl = BackupDSL.new(@config.backup_config)
|
|
84
|
+
backup_dsl.instance_eval(&block)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class EnvDSL
|
|
90
|
+
def initialize(config)
|
|
91
|
+
@config = config
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def set(key, value)
|
|
95
|
+
@config.instance_variable_get(:@env_vars)[key.to_s] = value.to_s
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# DSL for the backups block
|
|
100
|
+
class BackupDSL
|
|
101
|
+
def initialize(backup_config)
|
|
102
|
+
@backup_config = backup_config
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def dynamodb(scope = :all)
|
|
106
|
+
if scope == :all
|
|
107
|
+
@backup_config.instance_variable_set(:@dynamodb_tables, :all)
|
|
108
|
+
else
|
|
109
|
+
tables = Array(scope)
|
|
110
|
+
@backup_config.instance_variable_set(:@dynamodb_tables, tables.map(&:to_s))
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def cognito(*exports)
|
|
115
|
+
@backup_config.instance_variable_set(:@cognito_exports, exports.flatten.map(&:to_sym))
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def s3(*buckets)
|
|
119
|
+
@backup_config.instance_variable_set(:@s3_buckets, buckets.flatten.map(&:to_sym))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def retention(opts = {})
|
|
123
|
+
current = @backup_config.instance_variable_get(:@retention)
|
|
124
|
+
merged = current.merge(opts.transform_keys(&:to_sym))
|
|
125
|
+
merged.transform_values! { |v| v.respond_to?(:to_i) ? v.to_i : v }
|
|
126
|
+
@backup_config.instance_variable_set(:@retention, merged)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -61,9 +61,9 @@ module Belt
|
|
|
61
61
|
|
|
62
62
|
def parse_models
|
|
63
63
|
model_files = Dir.glob(File.join(MODELS_DIR, '*.rb'))
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
.reject { |f| File.basename(f) == 'application_record.rb' }
|
|
65
|
+
.reject { |f| File.basename(f).start_with?('concerns') }
|
|
66
|
+
.sort
|
|
67
67
|
|
|
68
68
|
model_files.filter_map { |f| parse_model_file(f) }
|
|
69
69
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'env_resolver'
|
|
4
|
+
require_relative 'environment_config'
|
|
4
5
|
|
|
5
6
|
module Belt
|
|
6
7
|
module CLI
|
|
@@ -53,6 +54,7 @@ module Belt
|
|
|
53
54
|
|
|
54
55
|
def run
|
|
55
56
|
validate!
|
|
57
|
+
apply_env_config!
|
|
56
58
|
env_dir = File.join(@infra_dir, @env)
|
|
57
59
|
args = ['terraform', @action, *@extra_args]
|
|
58
60
|
puts "belt → #{args.join(' ')} (in #{env_dir}/)"
|
|
@@ -61,6 +63,12 @@ module Belt
|
|
|
61
63
|
|
|
62
64
|
private
|
|
63
65
|
|
|
66
|
+
def apply_env_config!
|
|
67
|
+
env_config = EnvironmentConfig.load(@env, infra_dir: @infra_dir)
|
|
68
|
+
env_config.apply!
|
|
69
|
+
puts " 🔑 Using AWS profile: #{env_config.aws_profile}" if env_config.aws_profile?
|
|
70
|
+
end
|
|
71
|
+
|
|
64
72
|
def validate!
|
|
65
73
|
unless @infra_dir
|
|
66
74
|
abort "Error: No infrastructure/ directory found. Run `belt generate environment #{@env}` first."
|
|
@@ -18,7 +18,7 @@ module Belt
|
|
|
18
18
|
|
|
19
19
|
allowed.any? do |pattern|
|
|
20
20
|
if pattern.include?('*')
|
|
21
|
-
regex = Regexp.new(
|
|
21
|
+
regex = Regexp.new("\\A#{Regexp.escape(pattern).gsub('\*', '[^.]+')}\\z")
|
|
22
22
|
regex.match?(origin)
|
|
23
23
|
else
|
|
24
24
|
pattern == origin
|
data/lib/belt/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: belt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stowzilla
|
|
@@ -78,6 +78,7 @@ files:
|
|
|
78
78
|
- lib/belt/cli/destroy_command.rb
|
|
79
79
|
- lib/belt/cli/env_resolver.rb
|
|
80
80
|
- lib/belt/cli/environment_command.rb
|
|
81
|
+
- lib/belt/cli/environment_config.rb
|
|
81
82
|
- lib/belt/cli/frontend_command.rb
|
|
82
83
|
- lib/belt/cli/frontend_deploy_command.rb
|
|
83
84
|
- lib/belt/cli/frontend_env_command.rb
|