Class: Belt::CLI::DnsCommand

Inherits:
Object
  • Object
show all
Includes:
AppDetection
Defined in:
lib/belt/cli/dns_command.rb

Constant Summary collapse

TEMPLATE_DIR =
File.expand_path('../../templates/dns', __dir__)
DNS_DIR =
'infrastructure/dns'

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AppDetection

#detect_app_name, #detect_environments, #detect_namespace, #find_contracts_file_path, #find_routes_file_path, #find_schema_file_path, #s3_safe_name

Constructor Details

#initialize(quiet: false) ⇒ DnsCommand

Returns a new instance of DnsCommand.



63
64
65
66
67
# File 'lib/belt/cli/dns_command.rb', line 63

def initialize(quiet: false)
  @app_name = detect_app_name
  @quiet = quiet
  @state_bucket = resolve_state_bucket
end

Class Method Details

.helpObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/belt/cli/dns_command.rb', line 35

def self.help
  <<~HELP
    Usage: belt dns <subcommand>

    Subcommands:
      deploy              Deploy the dns infrastructure (init → plan → apply)
      generate            Create the infrastructure/dns directory (same as belt generate dns)
      add <env>           Add an environment's NS records to dns/terraform.tfvars
      help                Show this help

    Examples:
      belt dns deploy                 # Deploy the root zone
      belt dns generate               # Scaffold infrastructure/dns
      belt dns add staging            # Add staging's NS records to tfvars

    The dns directory manages your root domain and delegates subdomains to
    per-environment hosted zones. Each environment (dev, staging, prod) gets
    its own Route 53 zone, and this root zone delegates to each of them.

    Workflow:
      1. belt deploy dev              # Deploy environments first
      2. belt dns generate            # Create infrastructure/dns
      3. belt dns add dev             # Add dev's NS records
      4. belt dns deploy              # Deploy root zone
      5. Update registrar NS records to output values
  HELP
end

.run(args) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/belt/cli/dns_command.rb', line 17

def self.run(args)
  subcommand = args.shift

  case subcommand
  when 'deploy', nil
    new.deploy(args)
  when 'generate', 'init'
    new.generate
  when 'add'
    new.add_environment(args)
  when '--help', '-h', 'help'
    puts help
  else
    puts "Unknown dns subcommand: #{subcommand}\n\n#{help}"
    exit 1
  end
end

Instance Method Details

#add_environment(args) ⇒ Object

--- Add Environment ---



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/belt/cli/dns_command.rb', line 139

def add_environment(args)
  env_name = args.shift

  if env_name.nil? || env_name.start_with?('-')
    puts 'Usage: belt dns add <env>'
    puts "\nExample: belt dns add staging"
    exit 1
  end

  env_dir = "infrastructure/#{env_name}"
  unless Dir.exist?(env_dir)
    puts "Environment #{env_name} not found at #{env_dir}/"
    exit 1
  end

  # Get NS records from environment
  ns_records = fetch_ns_records(env_name)
  if ns_records.nil? || ns_records.empty?
    puts "Could not fetch NS records for #{env_name}."
    puts "\nMake sure the environment is deployed:"
    puts "  belt deploy #{env_name}"
    exit 1
  end

  # Update terraform.tfvars
  tfvars_path = "#{DNS_DIR}/terraform.tfvars"
  unless File.exist?(tfvars_path)
    puts "#{tfvars_path} not found. Run 'belt dns generate' first."
    exit 1
  end

  update_tfvars(tfvars_path, env_name, ns_records)
  puts "āœ“ Added #{env_name} NS records to #{tfvars_path}"
  puts "\nRun 'belt dns deploy' to apply the changes."
end

#deploy(args) ⇒ Object

--- Deploy ---



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/belt/cli/dns_command.rb', line 108

def deploy(args)
  unless Dir.exist?(DNS_DIR)
    puts 'No infrastructure/dns directory found.'
    puts "\nCreate it first:"
    puts '  belt dns generate'
    exit 1
  end

  auto = args.include?('--auto') || args.include?('-y')
  env_config = load_dns_config

  Dir.chdir(DNS_DIR) do
    run_terraform('init', env_config)
    run_terraform('plan', env_config, '-out=tfplan')

    if auto
      run_terraform('apply', env_config, 'tfplan')
    else
      print "\nApply this plan? [y/N] "
      answer = $stdin.gets&.strip&.downcase
      if %w[y yes].include?(answer)
        run_terraform('apply', env_config, 'tfplan')
      else
        puts 'Aborted.'
        exit 1
      end
    end
  end
end

#generateObject

--- Generate ---



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/belt/cli/dns_command.rb', line 70

def generate
  if Dir.exist?(DNS_DIR)
    puts "dns infrastructure already exists at #{DNS_DIR}/"
    puts "\nTo configure it:"
    puts "  1. Edit #{DNS_DIR}/terraform.tfvars with your domain and environment NS records"
    puts '  2. Run: belt dns deploy'
    exit 1
  end

  puts 'Creating dns infrastructure...' unless @quiet
  FileUtils.mkdir_p(DNS_DIR)

  templates.each do |template_name, dest_file|
    dest_path = File.join(DNS_DIR, dest_file)
    write_template(template_name, dest_path)
    puts "  create  #{dest_path}" unless @quiet
  end

  return if @quiet

  puts "\nāœ“ dns infrastructure created!"
  puts "\nThis manages your root domain and delegates subdomains to per-environment zones."
  puts "\nNext steps:"
  puts '  1. Deploy your environments first (if not already deployed):'
  puts '       belt deploy dev'
  puts '       belt deploy staging'
  puts ''
  puts '  2. Add each environment\'s NS records:'
  puts '       belt dns add dev'
  puts '       belt dns add staging'
  puts ''
  puts '  3. Deploy the dns infrastructure:'
  puts '       belt dns deploy'
  puts ''
  puts '  4. Update your registrar\'s NS records to the root_name_servers output'
end