kamal-backup 0.3.0.beta21 → 0.3.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.
@@ -1,10 +1,12 @@
1
- require "erb"
2
- require "uri"
3
- require "yaml"
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+ require 'uri'
5
+ require 'yaml'
4
6
 
5
7
  module KamalBackup
6
8
  class RailsApp
7
- DEVELOPMENT_ENV = "development"
9
+ DEVELOPMENT_ENV = 'development'
8
10
 
9
11
  def initialize(cwd:)
10
12
  @cwd = File.expand_path(cwd)
@@ -17,136 +19,135 @@ module KamalBackup
17
19
  defaults.merge!(deploy_defaults)
18
20
  defaults.merge!(database_defaults)
19
21
 
20
- if local_storage_path
21
- defaults["BACKUP_PATHS"] = local_storage_path
22
- end
22
+ defaults['BACKUP_PATHS'] = local_storage_path if local_storage_path
23
23
 
24
- defaults["KAMAL_BACKUP_STATE_DIR"] = File.join(@cwd, "tmp", "kamal-backup")
24
+ defaults['KAMAL_BACKUP_STATE_DIR'] = File.join(@cwd, 'tmp', 'kamal-backup')
25
25
  end
26
26
  end
27
27
 
28
28
  private
29
- def rails_app?
30
- File.file?(database_config_path)
31
- end
32
29
 
33
- def deploy_defaults
34
- service = fetch(parsed_yaml(deploy_config_path), :service)
30
+ def rails_app?
31
+ File.file?(database_config_path)
32
+ end
35
33
 
36
- if service
37
- { "APP_NAME" => service.to_s }
38
- else
39
- {}
40
- end
34
+ def deploy_defaults
35
+ service = fetch(parsed_yaml(deploy_config_path), :service)
36
+
37
+ if service
38
+ { 'APP_NAME' => service.to_s }
39
+ else
40
+ {}
41
41
  end
42
+ end
42
43
 
43
- def database_defaults
44
- config = local_database_config
45
- return {} unless config
44
+ def database_defaults
45
+ config = local_database_config
46
+ return {} unless config
46
47
 
47
- if url = fetch(config, :url)
48
- adapter = adapter_from_url(url)
48
+ if (url = fetch(config, :url))
49
+ adapter = adapter_from_url(url)
49
50
 
51
+ {
52
+ 'DATABASE_ADAPTER' => adapter,
53
+ 'DATABASE_URL' => url.to_s
54
+ }.compact
55
+ else
56
+ case normalize_adapter(fetch(config, :adapter))
57
+ when 'postgres'
50
58
  {
51
- "DATABASE_ADAPTER" => adapter,
52
- "DATABASE_URL" => url.to_s
59
+ 'DATABASE_ADAPTER' => 'postgres',
60
+ 'PGHOST' => fetch(config, :host),
61
+ 'PGPORT' => fetch(config, :port)&.to_s,
62
+ 'PGUSER' => fetch(config, :username),
63
+ 'PGDATABASE' => fetch(config, :database)
53
64
  }.compact
54
- else
55
- case normalize_adapter(fetch(config, :adapter))
56
- when "postgres"
57
- {
58
- "DATABASE_ADAPTER" => "postgres",
59
- "PGHOST" => fetch(config, :host),
60
- "PGPORT" => fetch(config, :port)&.to_s,
61
- "PGUSER" => fetch(config, :username),
62
- "PGDATABASE" => fetch(config, :database)
63
- }.compact
64
- when "mysql"
65
+ when 'mysql'
66
+ {
67
+ 'DATABASE_ADAPTER' => 'mysql',
68
+ 'MYSQL_HOST' => fetch(config, :host),
69
+ 'MYSQL_PORT' => fetch(config, :port)&.to_s,
70
+ 'MYSQL_USER' => fetch(config, :username),
71
+ 'MYSQL_DATABASE' => fetch(config, :database)
72
+ }.compact
73
+ when 'sqlite'
74
+ database = fetch(config, :database)
75
+ if database
65
76
  {
66
- "DATABASE_ADAPTER" => "mysql",
67
- "MYSQL_HOST" => fetch(config, :host),
68
- "MYSQL_PORT" => fetch(config, :port)&.to_s,
69
- "MYSQL_USER" => fetch(config, :username),
70
- "MYSQL_DATABASE" => fetch(config, :database)
71
- }.compact
72
- when "sqlite"
73
- database = fetch(config, :database)
74
- if database
75
- {
76
- "DATABASE_ADAPTER" => "sqlite",
77
- "SQLITE_DATABASE_PATH" => File.expand_path(database.to_s, @cwd)
78
- }
79
- else
80
- {}
81
- end
77
+ 'DATABASE_ADAPTER' => 'sqlite',
78
+ 'SQLITE_DATABASE_PATH' => File.expand_path(database.to_s, @cwd)
79
+ }
82
80
  else
83
81
  {}
84
82
  end
83
+ else
84
+ {}
85
85
  end
86
86
  end
87
+ end
87
88
 
88
- def local_storage_path
89
- File.join(@cwd, "storage")
90
- end
89
+ def local_storage_path
90
+ File.join(@cwd, 'storage')
91
+ end
91
92
 
92
- def local_database_config
93
- environment = fetch(parsed_yaml(database_config_path), DEVELOPMENT_ENV)
94
- return nil unless environment.is_a?(Hash)
93
+ def local_database_config
94
+ environment = fetch(parsed_yaml(database_config_path), DEVELOPMENT_ENV)
95
+ return nil unless environment.is_a?(Hash)
95
96
 
96
- if database_entry?(environment)
97
- environment
98
- else
99
- primary = fetch(environment, :primary)
100
- primary if primary.is_a?(Hash)
101
- end
97
+ if database_entry?(environment)
98
+ environment
99
+ else
100
+ primary = fetch(environment, :primary)
101
+ primary if primary.is_a?(Hash)
102
102
  end
103
+ end
103
104
 
104
- def database_entry?(config)
105
- fetch(config, :adapter) || fetch(config, :database) || fetch(config, :url)
106
- end
105
+ def database_entry?(config)
106
+ fetch(config, :adapter) || fetch(config, :database) || fetch(config, :url)
107
+ end
107
108
 
108
- def adapter_from_url(url)
109
- normalize_adapter(URI.parse(url.to_s).scheme)
110
- rescue URI::InvalidURIError
111
- nil
112
- end
109
+ def adapter_from_url(url)
110
+ normalize_adapter(URI.parse(url.to_s).scheme)
111
+ rescue URI::InvalidURIError
112
+ nil
113
+ end
113
114
 
114
- def parsed_yaml(path)
115
- return {} unless File.file?(path)
115
+ def parsed_yaml(path)
116
+ return {} unless File.file?(path)
116
117
 
117
- rendered = ERB.new(File.read(path), trim_mode: "-").result
118
- data = YAML.safe_load(rendered, permitted_classes: [], aliases: true)
118
+ rendered = ERB.new(File.read(path), trim_mode: '-').result
119
+ data = YAML.safe_load(rendered, permitted_classes: [], aliases: true)
119
120
 
120
- if data.is_a?(Hash)
121
- data
122
- else
123
- {}
124
- end
125
- rescue Psych::SyntaxError => e
126
- raise ConfigurationError, "invalid YAML in #{path}: #{e.message}"
121
+ if data.is_a?(Hash)
122
+ data
123
+ else
124
+ {}
127
125
  end
126
+ rescue Psych::SyntaxError => e
127
+ raise ConfigurationError, "invalid YAML in #{path}: #{e.message}"
128
+ end
128
129
 
129
- def fetch(hash, key)
130
- hash[key] || hash[key.to_s] || hash[key.to_sym]
131
- end
130
+ def fetch(hash, key)
131
+ hash[key] || hash[key.to_s] || hash[key.to_sym]
132
+ end
132
133
 
133
- def normalize_adapter(value)
134
- case value.to_s.downcase
135
- when "postgres", "postgresql"
136
- "postgres"
137
- when "mysql", "mysql2", "mariadb"
138
- "mysql"
139
- when "sqlite", "sqlite3"
140
- "sqlite"
141
- end
134
+ def normalize_adapter(value)
135
+ case value.to_s.downcase
136
+ when 'postgres', 'postgresql'
137
+ 'postgres'
138
+ when 'mysql', 'mysql2', 'mariadb'
139
+ 'mysql'
140
+ when 'sqlite', 'sqlite3'
141
+ 'sqlite'
142
142
  end
143
+ end
143
144
 
144
- def database_config_path
145
- File.join(@cwd, "config", "database.yml")
146
- end
145
+ def database_config_path
146
+ File.join(@cwd, 'config', 'database.yml')
147
+ end
147
148
 
148
- def deploy_config_path
149
- File.join(@cwd, "config", "deploy.yml")
150
- end
149
+ def deploy_config_path
150
+ File.join(@cwd, 'config', 'deploy.yml')
151
+ end
151
152
  end
152
153
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KamalBackup
2
4
  class Redactor
3
5
  SECRET_KEY_PATTERN = /(pass|password|secret|token|key|credential|authorization)/i
4
6
  SENSITIVE_KEY_PATTERN = /(?:pass|password|secret|token|key|credential|authorization)|\A(?:user|username|pguser|.*_user|.*_username)\z/i
5
- REDACTED = "[REDACTED]"
7
+ REDACTED = '[REDACTED]'
6
8
 
7
9
  def initialize(secret_values: [], env: ENV)
8
10
  @secret_values = Array(secret_values).compact.map(&:to_s).reject { |value| value.empty? || value.length < 4 }
@@ -31,22 +33,25 @@ module KamalBackup
31
33
  end
32
34
 
33
35
  private
34
- def known_secret_values
35
- @known_secret_values ||= begin
36
- env_secrets = @env.each_with_object([]) do |(key, value), values|
37
- values << value.to_s if key.to_s.match?(SECRET_KEY_PATTERN)
38
- end
39
36
 
40
- (@secret_values + env_secrets).compact.uniq.reject { |value| value.empty? || value.length < 4 }
37
+ def known_secret_values
38
+ @known_secret_values ||= begin
39
+ env_secrets = @env.each_with_object([]) do |(key, value), values|
40
+ values << value.to_s if key.to_s.match?(SECRET_KEY_PATTERN)
41
41
  end
42
+
43
+ (@secret_values + env_secrets).compact.uniq.reject { |value| value.empty? || value.length < 4 }
42
44
  end
45
+ end
43
46
 
44
- def redact_url_credentials(value)
45
- value.gsub(%r{(://)([^/\s]+)@}) do
46
- "#{$1}#{REDACTED}@"
47
- end.gsub(/([?&](?:password|token|secret|key|access_key_id|secret_access_key)=)[^&\s]+/i) do
48
- "#{$1}#{REDACTED}"
49
- end
47
+ def redact_url_credentials(value)
48
+ redacted = value.gsub(%r{(://)([^/\s]+)@}) do
49
+ "#{::Regexp.last_match(1)}#{REDACTED}@"
50
50
  end
51
+
52
+ redacted.gsub(/([?&](?:password|token|secret|key|access_key_id|secret_access_key)=)[^&\s]+/i) do
53
+ "#{::Regexp.last_match(1)}#{REDACTED}"
54
+ end
55
+ end
51
56
  end
52
57
  end