1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
7 class YAMLTree < Psych::Visitors::Visitor
8 def visit_ActiveSupport_Duration o
12 outstr += "#{seconds / 3600}h"
13 seconds = seconds % 3600
16 outstr += "#{seconds / 60}m"
17 seconds = seconds % 60
20 outstr += "#{seconds}s"
25 @emitter.scalar outstr, nil, nil, true, false, Nodes::Scalar::ANY
28 def visit_URI_Generic o
29 @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
33 @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
37 @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
44 # "foo.bar = baz" --> { cfg["foo"]["bar"] = baz }
58 $config_migrate_map = {}
60 def declare_config(assign_to, configtype, migrate_from=nil, migrate_fn=nil)
62 $config_migrate_map[migrate_from] = migrate_fn || ->(cfg, k, v) {
63 set_cfg cfg, assign_to, v
66 $config_types[assign_to] = configtype
70 class TrueClass; include Boolean; end
71 class FalseClass; include Boolean; end
73 class NonemptyString < String
76 def parse_duration durstr
77 duration_re = /(\d+(\.\d+)?)(s|m|h)/
80 mt = duration_re.match durstr
82 raise "#{cfgkey} not a valid duration: '#{cfg[k]}', accepted suffixes are s, m, h"
84 multiplier = {s: 1, m: 60, h: 3600}
85 dursec += (Float(mt[1]) * multiplier[mt[3].to_sym])
86 durstr = durstr[mt[0].length..-1]
91 def migrate_config from_config, to_config
93 from_config.each do |k, v|
94 if $config_migrate_map[k.to_sym]
95 $config_migrate_map[k.to_sym].call to_config, k, v
103 def coercion_and_check check_cfg
104 $config_types.each do |cfgkey, cfgtype|
117 raise "missing #{cfgkey}"
120 if cfgtype == String and !cfg[k]
124 if cfgtype == String and cfg[k].is_a? Symbol
128 if cfgtype == Pathname and cfg[k].is_a? String
131 cfg[k] = Pathname.new("")
133 cfg[k] = Pathname.new(cfg[k])
135 raise "#{cfgkey} path #{cfg[k]} does not exist"
140 if cfgtype == NonemptyString
141 if (!cfg[k] || cfg[k] == "")
142 raise "#{cfgkey} cannot be empty"
144 if cfg[k].is_a? String
149 if cfgtype == ActiveSupport::Duration
150 if cfg[k].is_a? Integer
151 cfg[k] = cfg[k].seconds
152 elsif cfg[k].is_a? String
153 cfg[k] = parse_duration cfg[k]
161 if !cfg[k].is_a? cfgtype
162 raise "#{cfgkey} expected #{cfgtype} but was #{cfg[k].class}"
168 def copy_into_config src, dst
170 dst.send "#{k}=", Marshal.load(Marshal.dump v)