Class: Restic::Service::Conf
- Inherits:
-
Object
- Object
- Restic::Service::Conf
- Defined in:
- lib/restic/service/conf.rb
Overview
The overall service configuration
This is the API side of the service configuration. The configuration is usually stored on disk in YAML and
The YAML format is as follows:
# The path to the underlying tools
tools:
restic: /opt/restic
rclone: /opt/rclone
# The targets. The only generic parts of a target definition
# are the name and type. The rest is target-specific
targets:
- name: a_restic_sftp_target
type: restic-sftp
See the README.md for more details about available targets
Defined Under Namespace
Classes: InvalidConfigurationFile, NoSuchTarget
Constant Summary collapse
- TARGET_CLASS_FROM_TYPE =
- TOOLS =
%w{restic rclone}- BANDWIDTH_SCALES =
Instance Attribute Summary collapse
-
#bandwidth_limit ⇒ nil, Integer
readonly
The bandwidth limit in bytes/s.
-
#conf_path ⇒ Pathname
readonly
The configuration path.
-
#period ⇒ Integer
readonly
The polling period in seconds.
Class Method Summary collapse
-
.default_conf ⇒ Object
The default (empty) configuration.
-
.load(path) ⇒ Conf
Load a configuration file.
-
.normalize_yaml(yaml) ⇒ Object
Normalizes and validates a configuration hash, as stored in YAML.
- .parse_bandwidth_limit(limit) ⇒ Object
-
.target_class_from_type(type) ⇒ Object
Returns the target class that will handle the given target type.
Instance Method Summary collapse
- #auto_update_restic? ⇒ Boolean
- #auto_update_restic_service? ⇒ Boolean
-
#conf_keys_path_for(target) ⇒ Object
The path to the key file for the given target.
-
#each_target(&block) ⇒ Object
Enumerates the targets.
-
#find_in_path(name) ⇒ Object
private
Helper that resolves a binary in PATH.
-
#initialize(conf_path) ⇒ Conf
constructor
A new instance of Conf.
-
#load_from_yaml(yaml) ⇒ void
Add the information stored in a YAML-like hash into this configuration.
-
#load_tools_from_yaml(yaml) ⇒ Object
private
Helper for #load_from_yaml.
-
#register_target(target) ⇒ Object
Registers a target.
- #restic_platform ⇒ Object
-
#target_by_name(name) ⇒ Target
Gets a target configuration.
-
#tool_available?(tool_name) ⇒ Boolean
Checks whether a given tool is available.
-
#tool_path(tool_name) ⇒ Pathname
The full path of a given tool.
Constructor Details
#initialize(conf_path) ⇒ Conf
Returns a new instance of Conf.
130 131 132 133 134 135 136 137 138 |
# File 'lib/restic/service/conf.rb', line 130 def initialize(conf_path) @conf_path = conf_path @targets = Hash.new @period = 3600 @tools = Hash.new TOOLS.each do |tool_name| @tools[tool_name] = find_in_path(tool_name) end end |
Instance Attribute Details
#bandwidth_limit ⇒ nil, Integer (readonly)
The bandwidth limit in bytes/s
Default is nil (none)
128 129 130 |
# File 'lib/restic/service/conf.rb', line 128 def bandwidth_limit @bandwidth_limit end |
#conf_path ⇒ Pathname (readonly)
The configuration path
114 115 116 |
# File 'lib/restic/service/conf.rb', line 114 def conf_path @conf_path end |
#period ⇒ Integer (readonly)
The polling period in seconds
Default is 1h (3600s)
121 122 123 |
# File 'lib/restic/service/conf.rb', line 121 def period @period end |
Class Method Details
.default_conf ⇒ Object
The default (empty) configuration
29 30 31 32 33 34 |
# File 'lib/restic/service/conf.rb', line 29 def self.default_conf Hash['targets' => [], 'period' => 3600, 'bandwidth_limit' => nil, 'tools' => Hash.new] end |
.load(path) ⇒ Conf
Load a configuration file
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/restic/service/conf.rb', line 98 def self.load(path) if !path.file? return Conf.new(Pathname.new("")) end yaml = YAML.load(path.read) || Hash.new yaml = normalize_yaml(yaml) conf = Conf.new(path.dirname) conf.load_from_yaml(yaml) conf end |
.normalize_yaml(yaml) ⇒ Object
Normalizes and validates a configuration hash, as stored in YAML
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 86 87 88 89 90 91 |
# File 'lib/restic/service/conf.rb', line 58 def self.normalize_yaml(yaml) yaml = default_conf.merge(yaml) TOOLS.each do |tool_name| yaml['tools'][tool_name] ||= tool_name end yaml['auto_update'] ||= Array.new target_names = Array.new yaml['targets'] = yaml['targets'].map do |target| if !target['name'] raise InvalidConfigurationFile, "missing 'name' field in target" elsif !target['type'] raise InvalidConfigurationFile, "missing 'type' field in target" end target_class = target_class_from_type(target['type']) if !target_class raise InvalidConfigurationFile, "target type #{target['type']} does not exist, available targets: #{TARGET_CLASS_FROM_TYPE.keys.sort.join(", ")}" end name = target['name'].to_s if target_names.include?(name) raise InvalidConfigurationFile, "duplicate target name '#{name}'" end target = target.dup target['name'] = name target = target_class.normalize_yaml(target) target_names << name target end yaml end |
.parse_bandwidth_limit(limit) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/restic/service/conf.rb', line 146 def self.parse_bandwidth_limit(limit) if !limit.respond_to?(:to_str) return Integer(limit) else match = /^(\d+)\s*(k|m|g)?$/.match(limit.downcase) if match return Integer(match[1]) * BANDWIDTH_SCALES.fetch(match[2]) else raise ArgumentError, "cannot interpret '#{limit}' as a valid bandwidth limit, give a plain number in bytes or use the k, M and G suffixes" end end end |
.target_class_from_type(type) ⇒ Object
Returns the target class that will handle the given target type
47 48 49 50 51 52 53 |
# File 'lib/restic/service/conf.rb', line 47 def self.target_class_from_type(type) if target_class = TARGET_CLASS_FROM_TYPE[type] return target_class else raise InvalidConfigurationFile, "target type #{type} does not exist, available targets: #{TARGET_CLASS_FROM_TYPE.keys.sort.join(", ")}" end end |
Instance Method Details
#auto_update_restic? ⇒ Boolean
224 225 226 |
# File 'lib/restic/service/conf.rb', line 224 def auto_update_restic? @auto_update_restic end |
#auto_update_restic_service? ⇒ Boolean
220 221 222 |
# File 'lib/restic/service/conf.rb', line 220 def auto_update_restic_service? @auto_update_restic_service end |
#conf_keys_path_for(target) ⇒ Object
The path to the key file for the given target
160 161 162 |
# File 'lib/restic/service/conf.rb', line 160 def conf_keys_path_for(target) conf_path.join("keys", "#{target.name}.keys") end |
#each_target(&block) ⇒ Object
Enumerates the targets
178 179 180 |
# File 'lib/restic/service/conf.rb', line 178 def each_target(&block) @targets.each_value(&block) end |
#find_in_path(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Helper that resolves a binary in PATH
190 191 192 193 194 195 196 197 198 |
# File 'lib/restic/service/conf.rb', line 190 def find_in_path(name) ENV['PATH'].split(File::PATH_SEPARATOR).each do |p| candidate = Pathname.new(p).join(name) if candidate.file? return candidate end end nil end |
#load_from_yaml(yaml) ⇒ void
This method returns an undefined value.
Add the information stored in a YAML-like hash into this configuration
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/restic/service/conf.rb', line 238 def load_from_yaml(yaml) load_tools_from_yaml(yaml['tools']) @period = Integer(yaml['period']) @bandwidth_limit = if limit_yaml = yaml['bandwidth_limit'] Conf.parse_bandwidth_limit(limit_yaml) end yaml['auto_update'].each do |update_target, do_update| if update_target == 'restic-service' @auto_update_restic_service = do_update elsif update_target == 'restic' @auto_update_restic = do_update end end yaml['targets'].each do |yaml_target| type = yaml_target['type'] target_class = Conf.target_class_from_type(type) target = target_class.new(yaml_target['name']) target.setup_from_conf(self, yaml_target) register_target(target) end end |
#load_tools_from_yaml(yaml) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Helper for #load_from_yaml
265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/restic/service/conf.rb', line 265 def load_tools_from_yaml(yaml) TOOLS.each do |tool_name| tool_path = Pathname.new(yaml[tool_name]) if tool_path.relative? tool_path = find_in_path(tool_path) end if tool_path && tool_path.file? @tools[tool_name] = tool_path else STDERR.puts "cannot find path to #{tool_name}" @tools.delete(tool_name) end end end |
#register_target(target) ⇒ Object
Registers a target
183 184 185 |
# File 'lib/restic/service/conf.rb', line 183 def register_target(target) @targets[target.name] = target end |
#restic_platform ⇒ Object
228 229 230 |
# File 'lib/restic/service/conf.rb', line 228 def restic_platform @auto_update_restic end |
#target_by_name(name) ⇒ Target
Gets a target configuration
169 170 171 172 173 174 175 |
# File 'lib/restic/service/conf.rb', line 169 def target_by_name(name) if target = @targets[name] target else raise NoSuchTarget, "no target named '#{name}'" end end |
#tool_available?(tool_name) ⇒ Boolean
Checks whether a given tool is available
204 205 206 |
# File 'lib/restic/service/conf.rb', line 204 def tool_available?(tool_name) @tools.has_key?(tool_name) end |
#tool_path(tool_name) ⇒ Pathname
The full path of a given tool
212 213 214 215 216 217 218 |
# File 'lib/restic/service/conf.rb', line 212 def tool_path(tool_name) if tool = @tools[tool_name] tool else raise ArgumentError, "cound not find '#{tool_name}'" end end |