Metaprogramming in OpsWorks recipes

The last time I worked on OpsWorks I needed to implement a recipe to handle the setup and configuration of cron jobs.

Actually I had already written some code to handle this functionality in the past. However, the recipe I ended up with wasn’t particularly flexible.

Continue reading “Metaprogramming in OpsWorks recipes”

Clean the kitchen, aka refactor cookbooks and recipes (Part 2)

Last time I described a general approach I used to decrease the amount of duplication across the recipes I developed in different cookbooks. The goals of these latter is to handle the deploy of specific PHP application via OpsWorks.

The PHP application I’m talking about are based in particular on WordPress (WP) and PrestaShop (PS).

Last time I also cited a “mysterious” recipe upon which I relied for setting the default attributes to specialize its behavior.

Continue reading “Clean the kitchen, aka refactor cookbooks and recipes (Part 2)”

Clean the kitchen, aka refactor cookbooks and recipes

I was planning to continue my series of posts entitled “Wordpress and OpsWorks, Pride and Prejudice”, but today I want to talk about something a little bit less specific. Anyway, for the curious readers, here’s the link with the last post of the aforementioned series.

The subject of this post doesn’t relate in particular to Opsworks or WordPress but it is still connected to these topics as it discusses “something” I found myself in need while working on a new cookbook containing some new recipes.

This something is the wish to refactor and it comes from the fact that the recipes of the new cookbook have a lot in common with the ones of the WordPress one. Just for the record, the purpose of the new recipes is to handle the deploy of another PHP framework (if WordPress can be considered a framework) called PrestaShop.

Anyway, pushed by the will to improve and dry out the structure of my cookbooks and recipes I started to delve more and more into the Chef docs and to study the other open source cookbooks.

Among all the sources I stumbled upon let me report this one as I consider it a great summary of the best practices regarding cookbooks and recipes development.

One of this best practices is to identify the type of the cookbooks you’re writing. This indeed will let you structure them in a more appropriate way and avoid, in many cases, a lot of duplication.

In my case for example, the WordPress and PrestaShop cookbooks can be considered as wrapper cookbooks for a more general one.

This last, i.e. the mysterious general cookbook, can be considered instead like an application cookbook. You can roughly think it like a sort of parent cookbook whose aim is to reduce the possible duplication between his children.

An example of these duplication is the recipe needed to handle the import of a database dump.

In this case the recipe is pretty general as it doesn’t rely on any specific data or behavior concerning the type of the application beeing deployed.

Here it is:


node['deploy'].each do |application, deploy|  
  attributes = deploy['set_db']
  
  next if deploy['application_type'] != 'php' or deploy['application'] != application
    
    import_db_dump do
      db deploy['database']
      db_dump attributes['db_dump']
    end
  
  end
  
end

The check I’m doing here (i.e. if deploy['application_type'] != 'php' or or deploy['application'] != application) is something I need in order to ensure that the recipe gets executed only for the current deployed application and not for the others allocated on the same OpsWorks stack. Remember, we’re using OpsWorks to handle all the operations and their related configurations.

The import_db_dump is just a definition I’ve written to add a little bit of magic and hide the details related to the import. Maybe one day I’ll show you those details… ;P

Now the important thing to remember about the recipe is that it resides inside a (general) application cookbook. I called it phpapps. So whenever I need to use the recipe inside a PHP layer defined inside an OpsWorks stack I must remember to specify the correct “path” to the recipe, in this case, phpapps::set_db.

This is really nothing special. The magic here (except from the one related to the import_db_dump definition 😉 ) is that OpsWorks will handle for us all the information we need in our recipe by automatically merge them not only with all the attributes specified inside the JSONs (i.e. the stack and the customs one) but also with the defaults attributes written inside the recipe cookbook.

In this way you can rely on these attributes in order to specialize the recipes.

As stated before this isn’t particularly the case as the recipe doesn’t use any application specific information.

Anyway in another general recipe I’ve written I rely on this feature and it seems to work pretty well.

Next time I’ll maybe describe the particularities of this misterious recipe as it need some tweaks to function properly.

Moreover it strongly relies on the default attributes of the cookbooks. These elements are indeed from my point of view the real cornerstone to properly structure the cookbooks as wrapper and application specific ones.

To the next time! 😉

Cheers!

Why JSON sucks for user configuration

In the current era of JavaScript JSON has become super common. In this article I want to make a point about it not being suitable for user configuration.

The good

Let’s start with the good parts. It’s not XML. Being born as a data interchange format from the mind of Douglas Crockford it shines for its simplicity in both the definition and easiness in parsing. That’s pretty much it. As a configuration tool the only good thing I can say is that many people are accustomed to it, and usually already know its rules.

The bad

As popular as it is the JSON format has started to be overused, especially for letting users to configure stuff (that’s the point of the article). The first thing to notice here is that JSON is not intended to be used that way, instead we can quote from the official page:

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate.

source: http://json.org

What I’d like to highlight is that JSON is a compromise between write/readability for both humans and machines. A data interchange format can easily be almost unreadable to humans, that happens all the time with binary formats but a configuration format should instead be biased towards humans.

The ugly

But what’s wrong with JSON?

I see three things that make JSON fail as a configuration format:

Strictness

The format is really demanding. Contrary to the ordinary JavaScript literal object format (which is where it comes from) JSON mandates double quotes around keys and strict absence of commas before closed parentheses.

Lack of comments

The absence of comments is perfectly fine in a data interchange formats where the payload will probably travel on wires and needs to be as tiny as possible. In a configuration format conversely it’s plain non-sense as they can be used to help the user explaining each configuration option or for the user to explain why he chose a particular option.

Readability

While JSON is quite readable when properly formatted, this good practice is not enforced by the format itself, so it’s up to coders good will to add returns, tabs and spaces in the right places. Lucky enough they usually do.

Conclusions

JSON has become very popular thanks to JavaScript to the point that is also a super common format for user configuration. It wasn’t designed to do so and in fact it does an awful job.

Almost anything is a good alternative, from INI to CSON. The one I like the most tho is YAML (which in turn has been erroneously used as a data interchange format). Here is the YAML tagline:

YAML is a human friendly data serialization standard for all programming languages.

source: http://yaml.org

WordPress and OpsWorks, “Pride and Prejudice” (Part 2)

Here we are for Part 2 🙂

In my last post about WP and OpsWorks I tried to explain the general setup for the recipes that I’ve developed to automate the deploy of WP applications through OpsWorks. If you missed it here’s the link.

Today I’m gonna talk about a particular problem that I encountered while writing the recipe that currently handles the database importation.

Continue reading “WordPress and OpsWorks, “Pride and Prejudice” (Part 2)”

Use the ENV Luke! aka: simulate the ENV in OpsWorks using Chef and Dotenv

OpsWorks is an impressive piece of software, but sometimes it lacks the comfort zone we developers love so much.
One feature that I really miss, is the ability to configure my application using ENV variables.
I’m not aware of any easy way (ie: Heroku like) to create environment variables in OpsWorks that the application can consume.

Fortunately OpsWorks is based on Chef and can be customized in any way you want.
Be warned, it’s not always an easy path, basic Chef knowledge is required, the interface is quite convoluted, but in the end it gets the job done.

So, we were saying environment!
We know environment is not supported in OpsWorks, so what we really need is to simulate it in some way.
A common solution among Rails developers, is the Dotenv gem which load the file .env in the root of you app and create the correspondent keys in the ENV object.

I will assume you already have created a Stack in OpsWorks with a Rails application layer.

Continue reading “Use the ENV Luke! aka: simulate the ENV in OpsWorks using Chef and Dotenv”

WordPress and OpsWorks, “Pride and Prejudice”

Disclaimer: this is not a comprensive tutorial nor a step by step guide on how to set up a WordPress site through Amazon OpsWorks.

I’m reporting only my personal experience and a few tips (borrowed form my colleagues) on how to write some recipes and how to use them to manage and deploy a WordPress website via OpsWorks.

But don’t despair, this may become the first article of a series dedicated to WordPress and OpsWorks.

Ok, let’s begin.

Continue reading “WordPress and OpsWorks, “Pride and Prejudice””