Skip to content

oclaussen/frebby

Repository files navigation

frebby

Gem Travis

What is this?

frebby is a very, very simple Ruby script that generates JSON out of a Ruby based configuration language. It is intended as an alternative to the numerous attempts to write a more human-readable language for tool configuration (YAML, TOML, HCL, to name a few).

In contrast to these other languages, frebby is not a full blown parser. Instead it takes a bunch of Ruby code, evals it and turns it into JSON. The result can then be fed to basically anything that can read JSON.

Why should I use this?

Everyone has a different opinion on how powerful a configuration language should be. Some people prefer a very strict and foolproof language while others prefer full blown programming languages. For most, the answer is somewhere in the middle. This tool is aimed at those who sit quite far in the programming language camp and who feel YAML and HCL are lacking in possibilities.

The Good

  • Use all the power of a full programming language for tools that usually wouldn't support this (Ansible, Terraform, Packer, ...)

  • Keep all your infrastructure defined in one consistent language

  • Works with anything that expects configuration files in JSON format (or YAML, or HCL, since these are just supersets of JSON)

  • No dependencies (except Ruby, of course)

The Bad

  • You need Ruby installed, and some level of Ruby knowledge will help also

  • It is another tool in you build chain and adds some level of complexity

  • There are some very good arguments for keeping the configuration for your infrastructure as simple and obvious as possible. Using a turing complete configuration language to set up the most critical parts of your infrastructure just asks for trouble. With great power and so on.

The Ugly

  • Due to the way frebby uses (abuses?) the Ruby programming language, there are some quirks where it will not immediately work the way you would expect. See the relevant examples details.

How do I use this?

Installation & Usage

At its core, frebby is just a very simple ruby script without dependencies. In theory, it is enough to just download the main file and put it anywhere in your $PATH. However, this won't get you the additional customization options. Instead there are more convenient options available:

Usually you will want to install frebby directly from rubygems:

gem install frebby

Once installed, usage is pretty simple: The frebby command simply takes any number of configuration files as input, either as arguments or from stdin, and output JSON on stdout. There are no other arguments or configurations to worry about.

frebby /path/to/config/file.rb /path/to/other/config.rb > /new/json/config.json

# alternatively:
frebby < /path/to/config/file.rb > /new/json/config.json

Aternatively, if you don't want to install Ruby locally, you can use frebby out of Docker:

docker pull oclaussen/frebby
docker run --rm -i oclaussen/frebby < /path/to/config/file.rb

Remember that you need to either pass your config files to the docker container via stdin or mount your working directory, so that frebby can find them.

Configuration syntax

Configuration for frebby is written in Ruby. The basic syntax looks like the love child of HCL and Chef's recipe DSL and should be immediately familiar to anyhone who has worked with either of them.

# Basic types (strings, numbers, lists, hashes) can be used just like
# in Ruby:

some_number 5

some_string <<EOF
This is
a very long
text
EOF

# Nested objects are created like this:

some_object 'some_nested_object' do
  some_key 'some value'
  some_other_key 'some other value'
end

# Lists of objects are created by repeated blocks:

some_list do
  some_key 'some value'
end

some_list do
  some_other_key 'some_other_value'
end

This example will produce the following JSON output (minus formatting):

{
  "some_number": 5,
  "some_string": "This is\na very long\ntext\n",
  "some_object": {
    "some_nested_object": {
      "some_key": "some value",
      "some_other_key": "some other value"
    }
  },
  "some_list": [
    {
      "some_key": "some value"
    },
    {
      "some_other_key": "some other value"
    }
  ]
}

For some more detailed examples, see the examples.

Customization

It is also possible to exert a little more control over how frebby translates to JSON.

# There are a bunch of customization functions available, that will act whenever
# frebby tries to transform a key, value or the whole end result

# Every translation goes through all registered customization functions, and
# will apply the first one that returns a non-null result.

require 'frebby/hooks'

::Frebby.customize_key do |key, **_data|
  'new_key' if %w[some_key some_other_key].include?(key)
end

::Frebby.customize_value do |value, **_data|
  value.sub('value', 'thing') if value.is_a? String
end

::Frebby.customize_result do |result, **_data|
  result['copied_field'] = result['copy_this']
  result
end

some_object do
  some_key 'some value'
  some_completely_other_key 'some completely other value'

  some_nested_object do
    some_other_key 'some other value'
  end
end

copy_this 'this value should be copied'

This example will produce the following JSON output:

{
  "some_object": {
    "new_key": "some thing",
    "some_completely_other_key": "some completely other thing",
    "some_nested_object": {
      "new_key": "some other thing"
    }
  },
  "copy_this": "this thing should be copied",
  "copied_field": "this thing should be copied"
}

frebby also offers some more convenience functions that take care of common use cases. There are also some useful presets for existing tools. Again, take a look at the examples for some inspiration.

License & Authors

Copyright 2018 Ole Claussen

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.