belt 0.3.17 → 0.3.19

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0f68a846160c9f0b0c3ecd69a74a3bf500531098cd29bf77b6a21cea22ece7a
4
- data.tar.gz: 55278ed99e4a8c886e55d12e83ed313aad88ff2953a3258b870e818c22a22a91
3
+ metadata.gz: c07291b16ac92bac6281fb35d39777453d87295f41b4de57bf2e7e1f5d2e82a2
4
+ data.tar.gz: 24a4b9fc917ce9f07a531a9f8d2b4d7b3a93e67d2095b1f7489f0a3551ca7748
5
5
  SHA512:
6
- metadata.gz: f22fef0b437a5e67f680ae5fc0a72ed9bc286006d635e3bddc68d886722cbdae8040953a8248972c2dbcd545d1eefcef3ce83dfb25c4caae6919afa2e1fafdc0
7
- data.tar.gz: c3e96290df0527f0b6da7c07469d8672c1dd41fcde7832cd2edb0997665b60f5ed69bd253f4189d23a24f28c910dc152d1572a7916aed0bca5a6eb5aea3bcb8c
6
+ metadata.gz: 7e6a5ec05148c1fe9cd01f6da381c88f1749021f587b76c1b10154d54210da6a46b52e82d1416f8160a20d682feb12254000b3b2fbc104b25f1505aa86bce6ea
7
+ data.tar.gz: ab4afd20f9f5f474bd7b4ea9fec32d17b360ff5c4d556c3b0a223b95c4d5d4210bd99fd3b4ab66bfdbee930c40eb3c26acb1705912a2bb81e77594a3f7a223d6
@@ -0,0 +1,313 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'erb'
5
+ require 'json'
6
+ require_relative 'app_detection'
7
+ require_relative 'environment_config'
8
+
9
+ module Belt
10
+ module CLI
11
+ class DnsCommand
12
+ TEMPLATE_DIR = File.expand_path('../../templates/dns', __dir__)
13
+ DNS_DIR = 'infrastructure/dns'
14
+
15
+ include AppDetection
16
+
17
+ def self.run(args)
18
+ subcommand = args.shift
19
+
20
+ case subcommand
21
+ when 'deploy', nil
22
+ new.deploy(args)
23
+ when 'generate', 'init'
24
+ new.generate
25
+ when 'add'
26
+ new.add_environment(args)
27
+ when '--help', '-h', 'help'
28
+ puts help
29
+ else
30
+ puts "Unknown dns subcommand: #{subcommand}\n\n#{help}"
31
+ exit 1
32
+ end
33
+ end
34
+
35
+ def self.help
36
+ <<~HELP
37
+ Usage: belt dns <subcommand>
38
+
39
+ Subcommands:
40
+ deploy Deploy the dns infrastructure (init → plan → apply)
41
+ generate Create the infrastructure/dns directory (same as belt generate dns)
42
+ add <env> Add an environment's NS records to dns/terraform.tfvars
43
+ help Show this help
44
+
45
+ Examples:
46
+ belt dns deploy # Deploy the root zone
47
+ belt dns generate # Scaffold infrastructure/dns
48
+ belt dns add staging # Add staging's NS records to tfvars
49
+
50
+ The dns directory manages your root domain and delegates subdomains to
51
+ per-environment hosted zones. Each environment (dev, staging, prod) gets
52
+ its own Route 53 zone, and this root zone delegates to each of them.
53
+
54
+ Workflow:
55
+ 1. belt deploy dev # Deploy environments first
56
+ 2. belt dns generate # Create infrastructure/dns
57
+ 3. belt dns add dev # Add dev's NS records
58
+ 4. belt dns deploy # Deploy root zone
59
+ 5. Update registrar NS records to output values
60
+ HELP
61
+ end
62
+
63
+ def initialize(quiet: false)
64
+ @app_name = detect_app_name
65
+ @quiet = quiet
66
+ @state_bucket = resolve_state_bucket
67
+ end
68
+
69
+ # --- Generate ---
70
+ def generate
71
+ if Dir.exist?(DNS_DIR)
72
+ puts "dns infrastructure already exists at #{DNS_DIR}/"
73
+ puts "\nTo configure it:"
74
+ puts " 1. Edit #{DNS_DIR}/terraform.tfvars with your domain and environment NS records"
75
+ puts ' 2. Run: belt dns deploy'
76
+ exit 1
77
+ end
78
+
79
+ puts 'Creating dns infrastructure...' unless @quiet
80
+ FileUtils.mkdir_p(DNS_DIR)
81
+
82
+ templates.each do |template_name, dest_file|
83
+ dest_path = File.join(DNS_DIR, dest_file)
84
+ write_template(template_name, dest_path)
85
+ puts " create #{dest_path}" unless @quiet
86
+ end
87
+
88
+ return if @quiet
89
+
90
+ puts "\n✓ dns infrastructure created!"
91
+ puts "\nThis manages your root domain and delegates subdomains to per-environment zones."
92
+ puts "\nNext steps:"
93
+ puts ' 1. Deploy your environments first (if not already deployed):'
94
+ puts ' belt deploy dev'
95
+ puts ' belt deploy staging'
96
+ puts ''
97
+ puts ' 2. Add each environment\'s NS records:'
98
+ puts ' belt dns add dev'
99
+ puts ' belt dns add staging'
100
+ puts ''
101
+ puts ' 3. Deploy the dns infrastructure:'
102
+ puts ' belt dns deploy'
103
+ puts ''
104
+ puts ' 4. Update your registrar\'s NS records to the root_name_servers output'
105
+ end
106
+
107
+ # --- Deploy ---
108
+ def deploy(args)
109
+ unless Dir.exist?(DNS_DIR)
110
+ puts 'No infrastructure/dns directory found.'
111
+ puts "\nCreate it first:"
112
+ puts ' belt dns generate'
113
+ exit 1
114
+ end
115
+
116
+ auto = args.include?('--auto') || args.include?('-y')
117
+ env_config = load_dns_config
118
+
119
+ Dir.chdir(DNS_DIR) do
120
+ run_terraform('init', env_config)
121
+ run_terraform('plan', env_config, '-out=tfplan')
122
+
123
+ if auto
124
+ run_terraform('apply', env_config, 'tfplan')
125
+ else
126
+ print "\nApply this plan? [y/N] "
127
+ answer = $stdin.gets&.strip&.downcase
128
+ if %w[y yes].include?(answer)
129
+ run_terraform('apply', env_config, 'tfplan')
130
+ else
131
+ puts 'Aborted.'
132
+ exit 1
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ # --- Add Environment ---
139
+ def add_environment(args)
140
+ env_name = args.shift
141
+
142
+ if env_name.nil? || env_name.start_with?('-')
143
+ puts 'Usage: belt dns add <env>'
144
+ puts "\nExample: belt dns add staging"
145
+ exit 1
146
+ end
147
+
148
+ env_dir = "infrastructure/#{env_name}"
149
+ unless Dir.exist?(env_dir)
150
+ puts "Environment #{env_name} not found at #{env_dir}/"
151
+ exit 1
152
+ end
153
+
154
+ # Get NS records from environment
155
+ ns_records = fetch_ns_records(env_name)
156
+ if ns_records.nil? || ns_records.empty?
157
+ puts "Could not fetch NS records for #{env_name}."
158
+ puts "\nMake sure the environment is deployed:"
159
+ puts " belt deploy #{env_name}"
160
+ exit 1
161
+ end
162
+
163
+ # Update terraform.tfvars
164
+ tfvars_path = "#{DNS_DIR}/terraform.tfvars"
165
+ unless File.exist?(tfvars_path)
166
+ puts "#{tfvars_path} not found. Run 'belt dns generate' first."
167
+ exit 1
168
+ end
169
+
170
+ update_tfvars(tfvars_path, env_name, ns_records)
171
+ puts "✓ Added #{env_name} NS records to #{tfvars_path}"
172
+ puts "\nRun 'belt dns deploy' to apply the changes."
173
+ end
174
+
175
+ private
176
+
177
+ def templates
178
+ {
179
+ 'main.tf.erb' => 'main.tf',
180
+ 'backend.tf.erb' => 'backend.tf',
181
+ 'variables.tf.erb' => 'variables.tf',
182
+ 'terraform.tfvars.erb' => 'terraform.tfvars',
183
+ 'outputs.tf.erb' => 'outputs.tf',
184
+ 'belt.rb.erb' => 'belt.rb'
185
+ }
186
+ end
187
+
188
+ def write_template(template_name, dest_path)
189
+ template_path = File.join(TEMPLATE_DIR, template_name)
190
+ content = ERB.new(File.read(template_path), trim_mode: '-').result(binding)
191
+ File.write(dest_path, content)
192
+ end
193
+
194
+ def load_dns_config
195
+ belt_rb = File.join(DNS_DIR, 'belt.rb')
196
+ return {} unless File.exist?(belt_rb)
197
+
198
+ EnvironmentConfig.load(belt_rb)
199
+ end
200
+
201
+ def run_terraform(action, env_config, *extra_args)
202
+ cmd = ['terraform', action] + extra_args
203
+ env = {}
204
+
205
+ if env_config[:aws_profile]
206
+ env['AWS_PROFILE'] = env_config[:aws_profile]
207
+ puts "Using AWS profile: #{env_config[:aws_profile]}" if action == 'init'
208
+ end
209
+
210
+ system(env, *cmd) || begin
211
+ puts "\n✗ terraform #{action} failed"
212
+ exit 1
213
+ end
214
+ end
215
+
216
+ def fetch_ns_records(env_name)
217
+ env_dir = "infrastructure/#{env_name}"
218
+ env_config = load_env_config(env_name)
219
+
220
+ env = {}
221
+ env['AWS_PROFILE'] = env_config[:aws_profile] if env_config[:aws_profile]
222
+
223
+ Dir.chdir(env_dir) do
224
+ # Try terraform output first
225
+ output, status = Open3.capture2e(env, 'terraform', 'output', '-json', 'name_servers')
226
+ if status.success?
227
+ begin
228
+ return JSON.parse(output)
229
+ rescue JSON::ParserError
230
+ # Fall through to state inspection
231
+ end
232
+ end
233
+
234
+ # Fallback: inspect state for the zone
235
+ output, status = Open3.capture2e(env, 'terraform', 'state', 'show', '-json',
236
+ 'module.app.aws_route53_zone.app[0]')
237
+ return nil unless status.success?
238
+
239
+ begin
240
+ state = JSON.parse(output)
241
+ state.dig('values', 'name_servers')
242
+ rescue JSON::ParserError
243
+ nil
244
+ end
245
+ end
246
+ end
247
+
248
+ def load_env_config(env_name)
249
+ belt_rb = "infrastructure/#{env_name}/belt.rb"
250
+ return {} unless File.exist?(belt_rb)
251
+
252
+ EnvironmentConfig.load(belt_rb)
253
+ end
254
+
255
+ def update_tfvars(path, env_name, ns_records)
256
+ content = File.read(path)
257
+
258
+ # Format the NS records for HCL
259
+ ns_list = ns_records.map { |ns| " \"#{ns}\"" }.join(",\n")
260
+ new_entry = " #{env_name} = [\n#{ns_list}\n ]"
261
+
262
+ # Check if environment_zones already has entries
263
+ if content =~ /environment_zones\s*=\s*\{([^}]*)\}/m
264
+ existing = ::Regexp.last_match(1).strip
265
+
266
+ if existing.empty?
267
+ # Empty block - replace with our entry
268
+ content.sub!(/environment_zones\s*=\s*\{\s*\}/, "environment_zones = {\n#{new_entry}\n}")
269
+ elsif existing.include?("#{env_name} =")
270
+ # Environment already exists - update it
271
+ content.sub!(/#{env_name}\s*=\s*\[[^\]]*\]/m, "#{env_name} = [\n#{ns_list}\n ]")
272
+ else
273
+ # Add to existing entries
274
+ content.sub!(/environment_zones\s*=\s*\{/m, "environment_zones = {\n#{new_entry}")
275
+ end
276
+ end
277
+
278
+ File.write(path, content)
279
+ end
280
+
281
+ # Resolve the state bucket name to use in backend.tf.
282
+ # Priority: existing sibling backend.tf → AWS account ID → bare placeholder.
283
+ def resolve_state_bucket
284
+ bucket_from_sibling || bucket_from_aws || 'belt-terraform-state'
285
+ end
286
+
287
+ def bucket_from_sibling
288
+ Dir.glob('infrastructure/*/backend.tf').each do |f|
289
+ match = File.read(f).match(/bucket\s*=\s*"([^"]+)"/)
290
+ next unless match
291
+ # Skip the bare placeholder — it means state wasn't set up yet
292
+ return match[1] unless match[1] == 'belt-terraform-state'
293
+ end
294
+ nil
295
+ end
296
+
297
+ def bucket_from_aws
298
+ require 'open3'
299
+ output, status = Open3.capture2e('aws', 'sts', 'get-caller-identity')
300
+ return nil unless status.success?
301
+
302
+ data = begin
303
+ JSON.parse(output)
304
+ rescue StandardError
305
+ nil
306
+ end
307
+ return nil unless data&.dig('Account')
308
+
309
+ "belt-terraform-state-#{data['Account']}"
310
+ end
311
+ end
312
+ end
313
+ end
@@ -64,6 +64,9 @@ module Belt
64
64
  puts ' domain = "..." # your domain (e.g., "myapp.com")'
65
65
  puts "\nThen deploy:"
66
66
  puts " belt deploy #{@env_name}"
67
+ puts "\nIf using multiple environments with a custom domain, run:"
68
+ puts ' belt dns generate'
69
+ puts 'to manage root domain delegation to per-environment zones.'
67
70
  end
68
71
 
69
72
  private
@@ -4,6 +4,7 @@ require 'fileutils'
4
4
  require 'erb'
5
5
  require_relative 'app_detection'
6
6
  require_relative 'auth_command'
7
+ require_relative 'dns_command'
7
8
  require_relative 'environment_command'
8
9
  require_relative 'frontend_command'
9
10
  require_relative 'frontend_registry'
@@ -17,7 +18,7 @@ module Belt
17
18
  class GenerateCommand
18
19
  TEMPLATE_DIR = File.expand_path('../../templates/generate', __dir__)
19
20
 
20
- GENERATORS = %w[scaffold resource model controller environment frontend views index auth].freeze
21
+ GENERATORS = %w[scaffold resource model controller environment frontend views index auth dns].freeze
21
22
 
22
23
  include AppDetection
23
24
 
@@ -91,6 +92,32 @@ module Belt
91
92
  Creates:
92
93
  lambda/controllers/<app>/<name>_controller.rb Controller class
93
94
  NOTES
95
+ },
96
+ 'dns' => {
97
+ description: 'Generate infrastructure for managing root domain DNS with multi-environment delegation.',
98
+ usage: 'belt generate dns',
99
+ options: [],
100
+ examples: [
101
+ ['belt g dns']
102
+ ],
103
+ notes: <<~NOTES
104
+ Creates:
105
+ infrastructure/dns/ Root DNS zone infrastructure
106
+ infrastructure/dns/belt.rb AWS profile configuration
107
+
108
+ This enables multiple environments (dev, staging, prod) to each have their own
109
+ hosted zone while sharing a single domain. The root zone delegates subdomains
110
+ to per-environment zones.
111
+
112
+ Workflow:
113
+ 1. Deploy environments first: belt deploy dev, belt deploy staging
114
+ 2. Add NS records: belt dns add dev, belt dns add staging
115
+ 3. Deploy: belt dns deploy
116
+ 4. Update your registrar's NS records to the root_name_servers output
117
+
118
+ For multi-account setups where DNS lives in a shared account:
119
+ Edit infrastructure/dns/belt.rb to set the AWS profile.
120
+ NOTES
94
121
  }
95
122
  }.freeze
96
123
 
@@ -127,6 +154,8 @@ module Belt
127
154
 
128
155
  return Belt::CLI::EnvironmentCommand.run(args) if generator == 'environment'
129
156
 
157
+ return Belt::CLI::DnsCommand.new.generate if generator == 'dns'
158
+
130
159
  return Belt::CLI::FrontendCommand.run(args) if generator == 'frontend'
131
160
 
132
161
  return Belt::CLI::ViewsCommand.run(args) if generator == 'views'
@@ -205,6 +234,7 @@ module Belt
205
234
  controller Generate a controller
206
235
  auth Generate Cognito user pool infrastructure
207
236
  environment Create a new deployment environment
237
+ dns Generate root DNS zone with multi-environment delegation
208
238
  frontend Scaffold a frontend app (react, vue, svelte; --name / --path for extras)
209
239
  views Generate React pages for a resource
210
240
 
data/lib/belt/cli.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'version'
4
4
  require_relative 'root'
5
+ require_relative 'cli/dns_command'
5
6
  require_relative 'cli/env_resolver'
6
7
  require_relative 'cli/new_command'
7
8
  require_relative 'cli/generate_command'
@@ -45,6 +46,7 @@ module Belt
45
46
  'plugin' => Belt::CLI::PluginCommand,
46
47
  'explain' => Belt::CLI::ExplainCommand,
47
48
  'deploy' => Belt::CLI::DeployCommand,
49
+ 'dns' => Belt::CLI::DnsCommand,
48
50
  'frontend' => Belt::CLI::FrontendEnvCommand,
49
51
  %w[server s] => Belt::CLI::ServerCommand,
50
52
  %w[version --version -v] => ->(_args) { puts "Belt #{Belt::VERSION}" }
@@ -103,6 +105,7 @@ module Belt
103
105
  generate frontend <react|vue|svelte> Scaffold a frontend app [--name --path]
104
106
  generate views <resource> [fields...] Generate React pages [--frontend NAME]
105
107
  generate environment <name> Create a new environment
108
+ generate dns Generate root DNS zone infrastructure
106
109
  destroy <scaffold|model|controller> <name> Remove generated components
107
110
  destroy frontend [--frontend NAME] Remove a frontend directory
108
111
  destroy views <resource> Remove React pages for a resource
@@ -111,6 +114,8 @@ module Belt
111
114
  s Alias for server
112
115
  deploy [environment] Deploy to AWS (init → plan → apply)
113
116
  deploy frontend <env> [--frontend NAME] Build and deploy frontend(s) to AWS
117
+ dns deploy Deploy root DNS zone (init → plan → apply)
118
+ dns add <env> Add environment NS records to dns/terraform.tfvars
114
119
  frontend env <env> [--frontend NAME] Write <frontend>/.env from terraform outputs
115
120
  frontend list List configured frontends
116
121
  routes [-g PATTERN] [-f json] Show route definitions
data/lib/belt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Belt
4
- VERSION = '0.3.17'
4
+ VERSION = '0.3.19'
5
5
  end
@@ -0,0 +1,8 @@
1
+ terraform {
2
+ backend "s3" {
3
+ bucket = "<%= @state_bucket %>"
4
+ key = "<%= @app_name %>/dns/terraform.tfstate"
5
+ region = "us-east-1"
6
+ encrypt = true
7
+ }
8
+ }
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ Belt.configure do |config|
4
+ # Set the AWS profile to use for DNS infrastructure.
5
+ # This can be a shared account for cross-environment DNS management,
6
+ # or the same profile as your environments for single-account setups.
7
+ #
8
+ # Example (shared DNS account):
9
+ # config.aws_profile = "sharedzilla"
10
+ #
11
+ # Example (same as environments):
12
+ # config.aws_profile = "myapp-dev"
13
+ #
14
+ # config.aws_profile = ""
15
+ end
@@ -0,0 +1,45 @@
1
+ # DNS Root Zone Configuration
2
+ # This module manages the root domain and delegates subdomains to per-environment
3
+ # hosted zones. This enables multiple environments (dev, staging, prod, etc.) to
4
+ # each have their own DNS zone while sharing a single domain.
5
+ #
6
+ # SETUP:
7
+ # 1. Deploy each environment first: belt deploy dev, belt deploy staging, etc.
8
+ # 2. Get each environment's NS records: cd infrastructure/<env> && terraform output name_servers
9
+ # 3. Add them to terraform.tfvars below
10
+ # 4. Apply this module: cd infrastructure/dns-root && terraform apply
11
+ # 5. Update your registrar's NS records to the root_name_servers output
12
+
13
+ terraform {
14
+ required_version = ">= 1.0"
15
+
16
+ required_providers {
17
+ aws = {
18
+ source = "hashicorp/aws"
19
+ version = ">= 5.0"
20
+ }
21
+ }
22
+ }
23
+
24
+ provider "aws" {
25
+ region = var.aws_region
26
+ }
27
+
28
+ # --- Root Hosted Zone ---
29
+ resource "aws_route53_zone" "root" {
30
+ name = var.domain
31
+ }
32
+
33
+ # --- Subdomain NS Delegation ---
34
+ # For each environment, create NS records that delegate to that environment's
35
+ # hosted zone. This allows dev.domain.com, staging.domain.com, etc. to resolve
36
+ # independently.
37
+ resource "aws_route53_record" "env_delegation" {
38
+ for_each = var.environment_zones
39
+
40
+ zone_id = aws_route53_zone.root.zone_id
41
+ name = "${each.key}.${var.domain}"
42
+ type = "NS"
43
+ ttl = 300
44
+ records = each.value
45
+ }
@@ -0,0 +1,14 @@
1
+ output "root_zone_id" {
2
+ description = "Route53 Hosted Zone ID for the root domain"
3
+ value = aws_route53_zone.root.zone_id
4
+ }
5
+
6
+ output "root_name_servers" {
7
+ description = "NS records to configure at your registrar (name.com, GoDaddy, etc.)"
8
+ value = aws_route53_zone.root.name_servers
9
+ }
10
+
11
+ output "delegated_environments" {
12
+ description = "Environments with NS delegation configured"
13
+ value = keys(var.environment_zones)
14
+ }
@@ -0,0 +1,22 @@
1
+ domain = "" # Your root domain (e.g., "myapp.com")
2
+
3
+ # NS records from each environment's hosted zone.
4
+ # After deploying an environment, get its NS records:
5
+ # cd infrastructure/<env> && terraform output name_servers
6
+ #
7
+ # Then add them here:
8
+ # environment_zones = {
9
+ # dev = [
10
+ # "ns-xxx.awsdns-xx.org",
11
+ # "ns-xxx.awsdns-xx.co.uk",
12
+ # "ns-xxx.awsdns-xx.com",
13
+ # "ns-xxx.awsdns-xx.net"
14
+ # ]
15
+ # staging = [
16
+ # "ns-yyy.awsdns-yy.org",
17
+ # "ns-yyy.awsdns-yy.co.uk",
18
+ # "ns-yyy.awsdns-yy.com",
19
+ # "ns-yyy.awsdns-yy.net"
20
+ # ]
21
+ # }
22
+ environment_zones = {}
@@ -0,0 +1,27 @@
1
+ variable "domain" {
2
+ description = "Root domain (e.g., myapp.com)"
3
+ type = string
4
+ }
5
+
6
+ variable "aws_region" {
7
+ description = "AWS region"
8
+ type = string
9
+ default = "us-east-1"
10
+ }
11
+
12
+ variable "environment_zones" {
13
+ description = <<-EOT
14
+ Map of environment names to their hosted zone NS records.
15
+ Get these values from each environment's Terraform output:
16
+ cd infrastructure/<env> && terraform output name_servers
17
+
18
+ Example:
19
+ environment_zones = {
20
+ dev = ["ns-1098.awsdns-09.org", "ns-2035.awsdns-62.co.uk", ...]
21
+ staging = ["ns-1318.awsdns-36.org", "ns-1762.awsdns-28.co.uk", ...]
22
+ prod = ["ns-111.awsdns-11.org", "ns-222.awsdns-22.co.uk", ...]
23
+ }
24
+ EOT
25
+ type = map(list(string))
26
+ default = {}
27
+ }
@@ -38,20 +38,22 @@ resource "aws_acm_certificate" "app" {
38
38
  # Key by resource_record_name (not domain_name) because ACM uses the same
39
39
  # validation CNAME for both base domain and wildcard — keying by domain_name
40
40
  # creates duplicate records that Route 53 rejects.
41
+ # Use ellipsis (...) to group duplicates, then take the first element since
42
+ # they're identical anyway.
41
43
  resource "aws_route53_record" "cert_validation" {
42
44
  for_each = local.dns_enabled ? {
43
45
  for dvo in aws_acm_certificate.app[0].domain_validation_options : dvo.resource_record_name => {
44
46
  name = dvo.resource_record_name
45
47
  type = dvo.resource_record_type
46
48
  record = dvo.resource_record_value
47
- }
49
+ }...
48
50
  } : {}
49
51
 
50
52
  zone_id = aws_route53_zone.app[0].zone_id
51
- name = each.value.name
52
- type = each.value.type
53
+ name = each.value[0].name
54
+ type = each.value[0].type
53
55
  ttl = 300
54
- records = [each.value.record]
56
+ records = [each.value[0].record]
55
57
  }
56
58
 
57
59
  resource "aws_acm_certificate_validation" "app" {
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.3.17
4
+ version: 0.3.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stowzilla
@@ -112,6 +112,7 @@ files:
112
112
  - lib/belt/cli/contracts_command.rb
113
113
  - lib/belt/cli/deploy_command.rb
114
114
  - lib/belt/cli/destroy_command.rb
115
+ - lib/belt/cli/dns_command.rb
115
116
  - lib/belt/cli/doctor_command.rb
116
117
  - lib/belt/cli/env_resolver.rb
117
118
  - lib/belt/cli/environment_command.rb
@@ -172,6 +173,12 @@ files:
172
173
  - lib/belt/views/welcome/show.html.erb
173
174
  - lib/belt_controller/base.rb
174
175
  - lib/belt_controller/implicit_response.rb
176
+ - lib/templates/dns/backend.tf.erb
177
+ - lib/templates/dns/belt.rb.erb
178
+ - lib/templates/dns/main.tf.erb
179
+ - lib/templates/dns/outputs.tf.erb
180
+ - lib/templates/dns/terraform.tfvars.erb
181
+ - lib/templates/dns/variables.tf.erb
175
182
  - lib/templates/environment/backend.tf.erb
176
183
  - lib/templates/environment/main.tf.erb
177
184
  - lib/templates/environment/outputs.tf.erb