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
32 # "foo.bar = baz" --> { cfg["foo"]["bar"] = baz }
46 $config_migrate_map = {}
48 def declare_config(assign_to, configtype, migrate_from=nil, migrate_fn=nil)
50 $config_migrate_map[migrate_from] = migrate_fn || ->(cfg, k, v) {
51 set_cfg cfg, assign_to, v
54 $config_types[assign_to] = configtype
58 class TrueClass; include Boolean; end
59 class FalseClass; include Boolean; end
61 class NonemptyString < String
64 def parse_duration durstr
65 duration_re = /(\d+(\.\d+)?)(s|m|h)/
68 mt = duration_re.match durstr
70 raise "#{cfgkey} not a valid duration: '#{cfg[k]}', accepted suffixes are s, m, h"
72 multiplier = {s: 1, m: 60, h: 3600}
73 dursec += (Float(mt[1]) * multiplier[mt[3].to_sym])
74 durstr = durstr[mt[0].length..-1]
79 def migrate_config from_config, to_config
81 from_config.each do |k, v|
82 if $config_migrate_map[k.to_sym]
83 $config_migrate_map[k.to_sym].call to_config, k, v
91 def coercion_and_check check_cfg
92 $config_types.each do |cfgkey, cfgtype|
105 raise "missing #{cfgkey}"
108 if cfgtype == String and !cfg[k]
112 if cfgtype == NonemptyString
113 if (!cfg[k] || cfg[k] == "")
114 raise "#{cfgkey} cannot be empty"
116 if cfg[k].is_a? String
121 if cfgtype == ActiveSupport::Duration
122 if cfg[k].is_a? Integer
123 cfg[k] = cfg[k].seconds
124 elsif cfg[k].is_a? String
125 cfg[k] = parse_duration cfg[k]
133 if !cfg[k].is_a? cfgtype
134 raise "#{cfgkey} expected #{cfgtype} but was #{cfg[k].class}"
140 def copy_into_config src, dst
142 dst.send "#{k}=", Marshal.load(Marshal.dump v)