Ruby YAML/Psych dump custom comments - ruby

I have various lang files in yaml. Every time I update one file, I want to track all the new keys, write them with the original text in all the other lang files, but delimited with ### NEW and ### END.
The translator will then periodically fetch them and update.
Example:
# it.yml
a: A
b: B
some:
new: Key
# en.yml
a: A
b: B
After I run the program, en.yml should be:
a: A
b: B
### NEW
some:
new: Key
### END
I've already done most of the work, updated the en object and tagged the new key in a custom object, but I cannot understand how to tell Psych to print out ### NEW and ### END.
Any help will be appreciated!
You can find the code here: https://gist.github.com/Iazel/4f5c9fcd9b33c3ea994c
EDIT:
After A LOT of searching, seems that libyaml doesn't support comments, hence I don't think is possible what I want to do... Not without extending libyaml at least.

Related

Get the keyname from a YAML configuration file

I would like to get the name of a key in a YAML configuration file like the following
The YAML file contains a collection of structs in structs, the organisations have a number represented as a symbol which is the key/class name. I need to retrieve this symbol
require 'yaml'
data = YAML.load(DATA)
data.organisations.each do |organisation|
organisation #<struct language="nl", name="myname">
# following line is what I need, I expect it to be :"121"
organisation.class #<Class:0x00000004fd4248>
end
__END__
--- !ruby/struct
organisations: !ruby/struct
:121: !ruby/struct
language: nl
name: organisationname
Can someone help me retrieving the name of the struct ?
I tried around a bit and found this:
data.organisations.members
=> [:"121"]
The way I found this (which is useful in other circumstances, too) is the following:
data.organisations.methods - Object.new.methods
And then I tried out every method that seemed reasonable.

Fetch variable from yaml in puppet manifest

I'm doing one project for puppet, however currently stuck in one logic.
Thus, want to know can we fetch variable from .yaml, .json or plain text file in puppet manifest file.
For example,
My puppet manifest want to create user but the variable exist in the .yaml or any configuration file, hence need to fetch the varibale from the outside file. The puppet manifest also can do looping if it exist multiple users in .yaml file.
I read about hiera but let say we are not using hiera is there any possible way.
There are a number of ways you can do this using a combination of built-in and stdlib functions, at least for YAML and JSON.
Using the built-in file function and the parseyaml or parsejson stdlib functions:
Create a file at mymodule/files/myfile.yaml:
▶ cat files/myfile.yaml
---
foo: bar
Then in your manifests read it into a string and parse it:
$myhash = parseyaml(file('mymodule/myfile.yaml'))
notice($myhash)
That will output:
Notice: Scope(Class[mymodule]): {foo => bar}
Or, using the loadyaml or loadjson stdlib functions:
$myhash = loadyaml('/etc/puppet/data/myfile.yaml')
notice($myhash)
The problem with that approach is that you need to know the path to file on the Puppet master. Or, you could use a Puppet 6 deferred function and read the data from a file on the agent node.
(Whether or not you should do this is another matter entirely - hint: answer is you almost certainly should be using Hiera - but that isn't the question you asked.)

How to write a file that is both valid ruby syntax and valid YAML syntax

In order to have only a single point of configuration for my app I need to make a YAML config file that is also valid ruby code. I.e. a mixed syntax file that can be parsed as YAML and parsed as ruby.
My application is a suite of processes managed by the god gem. I want to load a new group of maintained processes (watches) for each new configuration file.
God allows loading a new app.god (ruby) file with new watches defined, but I don't want an app.god and app.yml, just one file. Simplest might be to just have the app.god file and include the configuration within that, but I preferred the idea of a yml file that was also valid ruby code.
#I found this that might be helpful:
#This is a valid ruby and a valid YAML file
#Comments are the same in YAML and ruby
true ?true:
- <<YAML.to_i
# At this point in ruby it is the contents of a here doc (that will be
# converted to an integer and negated if true happens not to be true)
# In YAML it is a hash with the first entry having key "true ?true"
# representing a list containing the string "- <<YAML.to_i"
# If your YAML object should be a list not a hash you could remove the first line
any_valid_yaml: from here
a_list:
- or
- anything
- really
#Then mark the end of the YAML document with
---
#And YAML is done and ignores anything from here on
#Next terminate the ruby here document
YAML
#Now we're in ruby world
#this = "pure ruby"
def anything(ruby)
"here"
end

Replace properties in one file from those in another in Ruby

I want to replace properties in one file from those in another. (I am new to ruby, and read about Ruby and YAML. I have a Java background)
Eg.
File 1
server_ip_address=$[ip]
value_threshold=$[threshold]
system_name=$[sys_name]
File 2
ip=192.168.1.1
threshold=10
sys_name=foo
The ruby script should replace the $ values by their real values (I do not know if $[] is the format used in ruby. Also do Files 1 and 2 have to be YAML files, or erb files?) and produce File 1 as :
server_ip_address=192.168.1.1
value_threshold=10
system_name=foo
I searched the web for this, but could not express it in the right keywords to find a solution/pointer to a solution/reference material on google. How can this be done by a ruby script?
Thanks
If you can switch the formats, this should be as easy as:
require 'yaml'
variables = YAML.load(File.open('file2.yaml'))
template = File.read('file1.conf')
puts template.gsub(/\$\[(\w+)\]/) { variables[$1] }
Your template can stay as-is, but the substitution file would look like:
ip: 192.168.1.1
threshold: 10
sys_name: foo
This makes it easy to read in using the YAML library.

Updating YML on a production server

I am using a YML file to store trivial data.
I can create yml:
File.open("data.yml", "w") do |yaml|
yaml.write(#some_hash.to_yaml)
end
And open yml:
path = File.expand_path(File.dirname(__FILE__))
#trivial_data = YAML.load_file("#{path}/../../../config/data.yml")
But I don't know how to update a file. Say I want to add another row:
4:
agent_id: 332
last: Wade
first: Jason
suffix: Sr
rep_number: 2
How do I open, and update the yaml file? And is this a good idea on a production server?
Combine what you have and that's what you should do:
path = File.expand_path(File.dirname(__FILE__))
trivial_data = YAML.load_file("#{path}/../../../config/data.yml")
# ... manipulate data ...
File.open("data.yml", "w") do |yaml|
yaml.write(trivial_data.to_yaml)
end
You can't add something to a file without writing to it. YaML is a serialization language, and it doesn't make much sense to try and manipulate it directly. There is no simpler way (that I know of) that isn't horribly prone to errors.

Resources