This may not even be possible, but here goes. I am working on a snmp project and have a yaml config file which contains this:
# /home/vagrant/.snob/snobrc.yml
---
dummy:
user: username
auth_pass: auth passphrase
priv_pass: priv passphrase
auth: MD5/SHA
crypto: AES/DES
‘dummy’ in this case is a test host name. I currently retrieve the contents via:
class Config
include YAML::Serializable
property dummy : Hash(String, String)
def self.load
File.exists?(PATH) ? Config.from_yaml File.read(PATH) : raise FileNotFoundError.new(PATH)
rescue ex
raise InvalidFileFormatError.new(ex.message)
end
end
config = Config.load
I would like to pass that name, ‘dummy’, into the class as the property name so I can access other hostnames. Something like:
config = Config.new(newhost).load
Is this even possible? I have tried all sorts of combinations and it seems as though my naive approach is showing. Any thoughts are greatly appreciated.
Thanks
what happens if you do like:
def self.load(name : String) : self
File.exists?(PATH) ? Config.from_yaml(File.read(PATH), root: name) : raise FileNotFoundError.new(PATH)
rescue ex
raise InvalidFileFormatError.new(ex.message)
end
EDIT: Nevermind, apparently only .from_json
has a root
property.
EDIT2: This would also only work if the Config
type defined each property and not just a general Hash
Is it feasible to wrap it in a NamedTuple
and then drill down into that key?
require "yaml"
pp NamedTuple(dummy: Hash(String, String)).from_yaml(<<-YAML)[:dummy]
---
dummy:
user: username
auth_pass: auth passphrase
priv_pass: priv passphrase
auth: MD5/SHA
crypto: AES/DES
YAML
@Blacksmoke16 , as per your edit2, that is what I’m running into. Each host as a property.
Using YAML::Any:
def fetch_credentials(config_file : String, hostname : String)
creds = YAML.parse(File.read(config_file))[hostname]
{user: creds["user"].to_s, auth_pass: creds["auth_pass"].to_s,
priv_pass: creds["priv_pass"].to_s, auth: creds["auth"].to_s,
crypto: creds["crypto"].to_s}
end
This is getting me by for now but, seems a little clumsy.
After thinking about it more I think you could change things up to make your Config
class more like a Registry
of Host
configurations. Could make a singleton instance of it, and expose a method to allow getting the configuration for a specific host. E.g. something like:
require "yaml"
DATA = <<-YAML
---
dummy:
user: username
auth_pass: auth passphrase
priv_pass: priv passphrase
auth: MD5/SHA
crypto: AES/DES
YAML
class Registry
record Host, user : String, auth_pass : String, priv_pass : String, auth : String, crypto : String do
include YAML::Serializable
end
private class_getter instance : self { new }
def self.get(name : String) : Host
self.instance.configurations[name]
end
protected getter configurations : Hash(String, Host)
private def initialize
@configurations = Hash(String, Host).from_yaml DATA
end
end
pp Registry.get "dummy"
3 Likes
Thank you so much for this solution. Lots to unpack here for me.