Module: Nvoi::Utils::ConfigLoader

Defined in:
lib/nvoi/utils/config_loader.rb

Overview

ConfigLoader handles loading and initializing configuration from encrypted files

Class Method Summary collapse

Class Method Details

.generate_keypairObject

Generate a new Ed25519 keypair using ssh-keygen



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/nvoi/utils/config_loader.rb', line 150

def self.generate_keypair
  temp_dir = Dir.mktmpdir("nvoi-keygen-")
  key_path = File.join(temp_dir, "id_nvoi")

  begin
    result = system(
      "ssh-keygen", "-t", "ed25519", "-N", "", "-C", "nvoi-deploy", "-f", key_path,
      out: File::NULL, err: File::NULL
    )

    raise Errors::ConfigError, "Failed to generate SSH keypair (ssh-keygen not available?)" unless result

    private_key = File.read(key_path)
    public_key = File.read("#{key_path}.pub").strip

    [private_key, public_key]
  ensure
    FileUtils.rm_rf(temp_dir)
  end
end

.get_database_credentials(db_config, namer = nil) ⇒ Object

Get database credentials from config



34
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/nvoi/utils/config_loader.rb', line 34

def get_database_credentials(db_config, namer = nil)
  return nil unless db_config

  adapter = db_config.adapter&.downcase
  return nil unless adapter

  provider = External::Database.provider_for(adapter)

  unless db_config.url.blank?
    creds = provider.parse_url(db_config.url)
    host_path = nil

    if provider.is_a?(External::Database::Sqlite) && namer && db_config.servers&.any?
      host_path = resolve_sqlite_host_path(db_config, namer, creds.database || "app.db")
    end

    return External::Database::Types::Credentials.new(
      user: creds.user,
      password: creds.password,
      host: creds.host,
      port: creds.port,
      database: creds.database,
      path: creds.path,
      host_path:
    )
  end

  # Fall back to secrets-based credentials
  case adapter
  when "postgres", "postgresql"
    External::Database::Types::Credentials.new(
      port: provider.default_port,
      user: db_config.secrets["POSTGRES_USER"],
      password: db_config.secrets["POSTGRES_PASSWORD"],
      database: db_config.secrets["POSTGRES_DB"]
    )
  when "mysql", "mysql2"
    External::Database::Types::Credentials.new(
      port: provider.default_port,
      user: db_config.secrets["MYSQL_USER"],
      password: db_config.secrets["MYSQL_PASSWORD"],
      database: db_config.secrets["MYSQL_DATABASE"]
    )
  when "sqlite", "sqlite3"
    External::Database::Types::Credentials.new(
      database: "app.db",
      host_path: resolve_sqlite_host_path(db_config, namer, "app.db")
    )
  else
    raise Errors::ConfigError, "Unsupported database adapter: #{adapter}"
  end
end

.load(config_path, credentials_path: nil, master_key_path: nil) ⇒ Object

Load reads and parses the deployment configuration from encrypted file



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/nvoi/utils/config_loader.rb', line 12

def load(config_path, credentials_path: nil, master_key_path: nil)
  working_dir = config_path.blank? ? "." : File.dirname(config_path)
  enc_path = credentials_path.blank? ? config_path : credentials_path

  manager = CredentialStore.new(working_dir, enc_path, master_key_path)
  plaintext = manager.read
  raise Errors::ConfigError, "Failed to decrypt credentials" unless plaintext

  data = YAML.safe_load(plaintext, permitted_classes: [Symbol])
  raise Errors::ConfigError, "Invalid config format" unless data.is_a?(Hash)

  deploy_config = Configuration::Deploy.new(data)
  cfg = Configuration::Root.new(deploy_config)

  load_ssh_keys(cfg)
  cfg.validate_config
  generate_resource_names(cfg)

  cfg
end