Otto: a modern developer's new best friend

September 28, 2015

What is Otto?

According to HashiCorp, Otto is the successor to Vagrant. A lot has changed since Vagrant was first introduced, and while Vagrant has seen massive improvements, it’s still essentially doing the very same thing it did when it was first released. With Otto, the entire workflow from local development to deployment has been reimagined.

Does Otto really replace Vagrant?

At the moment, it doesn’t. In fact, Otto is using Vagrant to implement its otto dev command. What it does do, is provide a new way of looking at things. Mitchell Hashimoto aptly described this in the HashiConf keynote as ‘Codification vs. Fossilization’, but more on that in the next section. For now, you can happily use both Vagrant and Otto alongside each other, and pick one over the other as you see fit.

Codification vs. Fossilization

This is basically what Otto is all about: a new approach. If you’ve used Vagrant before, you know you had to provide a Vagrantfile, which would then be used to build a virtual environment. You would pull in a ‘base box’, or VM image, boot it, and provision it with scripts or Puppet/Chef code. It would turn out exactly the same every time you would run vagrant up, regardless of the machine you would run it on, and regardless of whether you would run vagrant up today, or 5 years from now. This is what HashiCorp calls ‘fossilization’.

With Otto, HashiCorp wants to get rid of fossilization. Instead they want to offer developers a way to describe their application, using something called an ‘AppFile’. An AppFile can look somewhat like this:

application {
  name = "otto-getting-started"
  type = "ruby"
}

project {
  name = "otto-getting-started"
  infrastructure = "otto-getting-started"
}

infrastructure "otto-getting-started" {
  type = "aws"
  flavor = "simple"
}

What you’ll notice is that the AppFile doesn’t mention anything about provisioning or base images. This is because we’re not trying to create a fossil. Instead we are describing our application, and Otto’s job is to use today’s best practices to do the rest. This means that when we run otto dev today, the environment we end up with is likely to be different from what we get when we run otto dev 5 years from now.

You may wonder why this is a good thing. After all, we liked Vagrant because it gave us a consistent and repeatable setup. And predictability is good, right? The answer is: yes, this is a good thing. The consistent and repeatable setups are still there, but because Otto is able to get smarter over time, and learn about new best practices, it will actually adapt the implementation of your AppFile to the latest best practices.

Developers want to deploy!

Vagrant worked pretty great for creating local development or demo environments, but it didn’t provide any functionality for builds, setting up production infrastructure, or deployments. But developers want to deploy. They want to build. And, sometimes, they want to set up their own infrastructure (or actually: they simply don’t want to wait for an ops department to do it for them). And they could. Before Otto, you could build your own images or Docker containers using Packer. You could set up infrastructure using Terraform. And you could probably find a way to deploy your app (shell scripts to the rescue!).

But seriously, who wants to learn 4 separate tools to do all this? And I haven’t even mentioned ‘glue tools’ like Consul and Vault yet. So actually, you’d need to acquaint yourself with 6 tools! No way!

Under the hood

So how does Otto fix all this? Well, basically by implementing all of them. Whenever you run otto dev, Otto runs Vagrant for you, but you didn’t have to write a Vagrantfile. When you run otto build, Otto runs Packer. Running otto infra, Otto quickly writes some Terraform code for you and runs it. And finally, when you run otto deploy, Otto deploys your build artifact to your infrastructure, and handles all the plumbing (Consul, Vault) for you. All according to today’s best practices.

Current limitations

Otto was just released today, so obviously there’s a ton of stuff it doesn’t do yet. For instance, the only type of infrastructure that is currently supported, is AWS. The application types are limited to Docker, Go, PHP, Node.js and Ruby, although you can use a ‘custom’ type, if you provide a custom Vagrantfile and Terraform module to ‘teach’ Otto how to use it. The fact that you need to create your own Vagrantfile/Terraform module may seem cumbersome, but the fact that we can actually do this, means it’s pretty easy to make Otto smarter.

Can we skip the infra part, please?

One thing I would like to see, is an option to use existing infrastructure instead of creating it by running otto infra. At many companies, there will be a platform team that actually provides infrastructure to the development/product teams, so it would be awesome if Otto could just use that. Let developers create their local environments with otto dev, build a Docker image with otto build and deploy their container against Nomad by running otto deploy.

You could use the ‘custom’ application type, as it forces you to provide your own custom Vagrantfile and Terraform code, to make sure Otto deploys on the shared platform your company might have, but that seems like way too much of a hassle when all you would really need is an option to not have Otto build any infrastructure, and a second option to provide an endpoint instead.

Your Personal DevOps Assistant

HashiCorp calls Otto the successor to Vagrant. I’d call Otto a modern developer’s new best friend. Otto is your personal DevOps Assistant. Otto is smart, and Otto will get smarter over time. But for now, Otto is still lacking some social skills and doesn’t work well with your existing platform teams yet. But nobody’s born perfect, right?