Chef ruby code - .rb cookbook - If statement to check config['variable'] exists - ruby

I have the following bit of code in my cookbook:
if File.file?('/etc/test.yml')
config = YAML.load(File.read('/etc/test.yml'))
else
config = Hash.new
end
config['license_key'] = node['test']['license']
config['verbose'] = 0
config['metrics_process_sample_rate'] = 60
file '/etc/test.yml' do
content config.to_yaml
end
My code works in that the .yml file will be created if it doesn't already exist and will populate the file with three variables when creating the .yml file. But what I'm attempting to add to this bit of code is to confirm if the .yml file already exists that these three variables also exist in the .yml file. I'll need to add a check to each config['variable'] = line confirm if this variable exists and if the variable is missing to add the variable to the .yml file.
Any advice on the code required to achieve this would be greatly appreciated.
Thank you.

config = Hash.new
if File.file?('/etc/test.yml')
config = YAML.load(File.read('/etc/test.yml'))
end
config['license_key'] ||= node['test']['license']
config['verbose'] ||= 0
config['metrics_process_sample_rate'] ||= 60
file '/etc/test.yml' do
content config.to_yaml
end

Related

In Ruby, how can I maintain a long list of instance variables from a file?

For example I store a lot of instance variables in a YAML file. This allow me to change the state of the program while it is running. However I need to change the method that reads the file every time I add a new variable.
e.g.
config = YAML.open_file 'config.yml'
#var1 = config["var1"]
#var2 = config["var2"]
#var3 = config["var3"]
#var4 = config["var4"]
#var5 = config["var5"]
...
How can I make this more dynamic and not need to change it as I add variables in the YAML file ?
Use Ruby meta-programming!
instance_variable_set is your friend here:
config = YAML.load_file 'config.yml'
config.each do |key,value|
instance_variable_set('#'+key, value)
end
Test:
puts #var1

Storing file names in an array

I'm trying to store the file names in some directory in an array. I have the following script:
files= Dir.glob('C:\Users\Abder-Rahman\Desktop\drugsatfda\*.*')
files.each do |filename|
contents = IO.read(filename)
puts contents
end
exit
But, I don't know why it doesn't work. What could I be missing?
Unfortunately, it is not described in documentation, but Dir.glob doesn't throw any exception in case you provided invalid path - it will return just empty array.
files = Dir.glob("./an/imaginary/directory/that/doesnt/exist/*")
# => []
Please, make sure, that the path you've provided both - exists, and has any files.

Ruby, writing to a YAML file, with arrays

I'm trying to save a few variables in a YAML config file.
Cool!!
However, when I try and save them, I get an error in RUBY:
undefined method `[]=' for false:FalseClass (NoMethodError)
My function should (In my head at least) be:
Does the config file exist, if not, just create a blank one.
Now that we know it exists, YAML.open it
set the new/overwriting key/value pairs
re Write the file
But, I'm getting the error above.
I'm new to Ruby (PHP bloke here), tell me where I'm being stupid please :)
def write_to_file( path_to_file, key, value, overwrite = true )
if !File.exist?(path_to_file)
File.open(path_to_file, 'a+')
end
config_file = YAML.load_file( path_to_file)
config_file[key] = value
File.open(path_to_file, 'w') { |f| YAML.dump(config_file, f) }
# I tried this commented code below too, same error..
# {|f| f.write config_file.to_yaml }
end
The problem is that you created an empty file. And the YAML parser returns false for an empty string:
YAML.load('') #=> false
Just set config_file to an empty hash when the YAML loader returned false:
config_file = YAML.load_file(path_to_file) || {}

how to raise an exception if a variable read from yaml file is not declared in the yaml file?

I am reading variables from a yaml file:
begin
settings = YAML.load_file 'vm.yaml'
$var_a = settings['var_a']
$var_b = settings['var_b']
....
$var_z = settings['var_z']
rescue
puts "\nInvalid vm.yaml - please create or recreate vm.yaml from vm.yaml.example\n\n"
exit 1
end
puts $var_a
If a variable is not set in the vm.yaml file, the error will not be detected until the variable is first accessed (e.g. at puts $var_a).
Preferably, I would like the code in the rescue block to be executed if the variable is not set in the yaml file.
What is the most rubyist way to do this?
Use a fetch instead of [] to access the hash data.
So instead of settings['var_a'] do settings.fetch('var_a')
By default, this will raise an error if the key does not exist. But the fetch method also takes an optional block that is executed if the key isn't found.
This can allow you to set up a default return value:
settings.fetch('var_a') { 'foo' }
or create a custom failure message:
settings.fetch('var_a') { fail "Key var_a was not found, please add it to the yaml" }

file extension dependend actions

I want to check if a directory has a ".ogg" or ".m4a" file. In every case the dir is empty before starting a download session. So it just can have one "ogg" or one "m4a" file.
I tried out this code to fetch the filename:
def self.get_filename
if File.exists?('*.ogg')
file = Dir.glob('*.ogg')
#testfile = file[0]
#filename = File.basename(#testfile,File.extname(#testfile))
end
if File.exists?('*.m4a')
file = Dir.glob('*.m4a')
#testfile = file[0]
#filename = File.basename(#testfile,File.extname(#testfile))
end
end
Sadly the filename is actual empty. Maybe anyone knows why?
I think that you need Dir.glob instead.
Dir.glob('/path/to/dir/*.ogg') do |ogg_file|
#testfile = ogg_file
#filename = File.basename(#testfile,File.extname(#testfile))
end
File#exists? does not support regular expressions.
You can do this instead:
if Dir["*.rb"].any?
#....

Resources