Terraframe: Making HashiCorp’s Terraform Awesome

So, Terraform is a cool infrastructure-as-code system with a boatload of functionality. It makes building out entire clouds on AWS1 super easy and super fun. I am a fan. I started my new job as Lead Platform Engineer at Leaf this week2, and I was really happy to have the chance to use Terraform in a greenfield project where I could play with it.

But I wasn’t happy with it, and so I’ve done a thing.

As a tool, Terraform is pretty good. It’s smart, it does the right thing when it comes to figuring out how to best apply your plan to your environment. But I had a real beef with it. Ever since HashiCorp went away from Ruby DSLs as configuration in their various projects, I have been sad. And worse than sad, I have been unproductive. I don’t like Packer’s config format and I really am just not satisfied with the state of the Terraform language’s3 grammar and semantics. It’s hard to write, its built-in assumptions are gross (the handling of variables is a minor crime in progress), and it’s just a huge step back from being able to deploy, say, a Vagrant instance–or, as I have done, a configurable number of Vagrant instances–in a nice, comprehensible manner.

So I did it. I broke out ye olde Ruby interpreter and, in the next three hours, out of my fingers came Terraframe, a tool that I think makes Terraform about a billion times nicer to use. It accepts any number of Terraframe scripts (themselves just Ruby files) and any number of YAML files (merged in sequence) and spits out a Terraform JSON file out of them4.

Terraframe isn’t at all done, so don’t expect miracles (yet) and there are probably all sorts of bugs because I’m still new to Terraform, this hasn’t been used in anger, and this is the first time I’ve ever used Ruby to write a DSL, but it’s performed fine in setting up the test cloud I’m building at Leaf. I’ll begin extending it over time—I’ll add provisioner smarts to it when I start needing provisioners, that sort of thing—and I’m sure I’ll fill it out further over time. You can get it on Github or download v0.0.5 via RubyGems with gem install terraframe.

Contributions, as usual, are welcome.


Comments

  1. Would love some detail on “the handling of variables is a minor crime in progress”. Anything specific and/or juicy? đŸ™‚

    Reply
    • Variables are all strings. (Everything is a string, until it hits validation.) There are no arrays; the recommended solution is to use their home-rolled interpolation silliness to split a comma-separated string into an array.

      It’s just…it’s badly conceived in a lot of ways and even today I’m super disappointed with it. Terraform in general is a real drag and I’m not at all a fan of it after my initial interest, but this is one of the more user-hostile parts of it in a system made of user-hostile parts.

      Reply
  2. Couldn’t agree more… currently trying to break out into modules for reusability and DRYness. Unfortunately from what I can tell, unless I’m missing something – defining variables in the module/s (EG a web stack with all its variable requirements, db stack with all its variables etc etc), then linking the resources together when wanting to actually create a full stack environment which utilises the modules, then I need to define the variables again in both the declaration of the module, another variables.tf file and a tfvars file (unless you want to hard code or pass in via command line) is really and truly not DRY at all. Also when you have even more than 2-3 types of re-useable modules that you want to pull in – it becomes quite difficult to automate in a clean manner. Very disappointed.

    Reply

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>