A Comparison: Puppet vs Otter

KB#1109: Last Updated Jan 11, 2018

Puppet and Otter are both infrastructure automation products, and if you only read the marketing bullets, they'd probably sound identical. But they're quite different products, and this article compares and contrasts the products and the philosophies behind them.

Moreover, there's nothing wrong with having and using both - in fact, many organizations have Puppet, Chef, and Otter, because they all serve different needs for different groups.

While we are not Puppet experts, we've done a ton of research on Puppet when building Otter and, more recently, for this article. Please let us know if something is inaccurate.

Already familiar with Puppet? The terminology comparison may help you get a quicker understanding of Otter.

Emerging vs Established

Otter launched in 2016, whereas Puppet celebrated their 10-year anniversary in 2015. Puppet is the established tool in the space, but so are the long-term challenges in its use. From "Moving Away from Puppet":

"[The Puppet code base] was large, unwieldy and complex, especially for our core application. Our DevOps team was getting accustomed to the Puppet infrastructure; however, Lyft is strongly rooted in the concept of ‘If you build it you run it'. The DevOps team felt that the Puppet infrastructure was too difficult to pick up quickly and would be impossible to introduce to our developers as the tool they'd use to manage their own services."

Although Puppet has evolved quite a bit over the past decade, its roots in Linux Configuration Management are well established, and can be awkward to transplant in today's modern, heterogeneous environments.

Otter was not only built specifically for today's infrastructure challenges, but we learned the challenges of implementing Puppet.

Puppet as Linux Configuration Management

Long before "DevOps" and "Infrastructure as Code" were even coined, CFEngine was the established Linux CM. A decade later, Puppet emerged with a new approach:

one of the big differences: cfengine focuses mostly on managing textfiles, while Puppet manages semantically more powerful constructs like users, services, and packages. Thus, Puppet has higher-level models than cfengine, and if you accept my premise that model power derives from how high-level it is, that generally makes Puppet a more powerful tool than cfengine

Clearly, the market agreed, and Puppet not only dominated Linux Configuration Management, but helped herald the concepts of DevOps and Infrastructure as Code.

The Windows Challenge

Although Puppet and the community have built a lot of Windows modules, the tool was never designed with Windows configuration management in mind, and Windows support often feels second-class.

Windows and Linux are very different; not just technologically, but philosophically. Although Windows has been lately offering administrators better command-line, scripting, and detachable components, they will always be two very different operating systems.

Otter was built with from the start with first-class Windows support (including tight integration with PowerShell), and was built using Windows-friendly technologies (.NET), and doesn't need to go through layers of Ruby for core functionality.

The Orchestration Challenge

Puppet's abstract configuration model is it's major strength, but is also a major weakness. Orchestration – that is, getting specific servers to do specific things in a specific order, like deploying large, multi-tier applications – is extremely challenging and awkward with Puppet.

While Puppet's Application Orchestration feature attempts to make this easier, it's still an afterthought that utilizes the same, fundamental configuration modeling approach.

Otter was designed with built-in orchestration jobs, not just for Linux and Windows, but cloud and virtualization provisioning as well.

In addition, Inedo is a Enterprise DevOps company, and our entire product suite and enabling tools uses the same, powerful execution engine, code base, and extensions providing a comprehensive DevOps solution.

Abstracted Configuration:
Real World vs Ideal World

Puppet models and abstracts configuration using manifests of resources. Essentially, you declaratively say "this type of server should have these resources (i.e. components installed and configured)," and Puppet will just make it happen.

Behind the scenes, a server with a Puppet agent installed routinely queries the Puppet master server, which uses the "facts" (current configuration) of the server to build a directed graph of resources and determine a run order. The agent then executes the necessary commands to ensure the desired state.

In an ideal world, the implementation details shouldn't matter, but as a decade worth of users can attest, this implementation has its challenges.

  • the apparent random application of resources (i.e. not running things in the top-down order in your manifest file) is unintuitive and confusing to anyone with experience in conventional programming or scripting languages
  • servers are responsible for configuring themselves, which makes multi-server orchestration basically impossible
  • a simple task, like "just run this script" doesn't fit into the resource model and is awkward

Otter does not model configuration, but has idempotent operations that give you the option to model configuration. Essentially, this means your plans will /look/ like declarative configuration when need them to be, but can be procedural when they have to be.

Consider this simple IIS configuration (from Puppet's IIS module), and the corresponding plan:

  • PuppetScript
  • OtterScript
class mywebsite {
    iis::manage_app_pool {'my_application_pool':
      enable_32_bit           => true,
      managed_runtime_version => 'v4.0',
    }
    iis::manage_site {'www.mysite.com':
      site_path     => 'C:\inetpub\wwwroot\mysite',
      port          => '80',
      ip_address    => '*',
      host_header   => 'www.mysite.com',
      app_pool      => 'my_application_pool'
    }
}
# mywebsite
{
    Ensure-AppPool my_application_pool
    (
        Runtime: v4.0,
        Enable32BitAppOnWin64: True
    );
    Ensure-Site www.mysite.com
    (
        AppPool: my_application_pool,
        Path: C:\inetpub\wwwroot\mysite,
        Binding: *:80:www.mysite.com
    );
}

So far, both are quite clear and the difference is entirely semantics. But let's add a real-world requirement: before making any IIS changes, run a script that will detach the server from the load balancer, and then run reattach it once the site has been tested.

This simple requirement is entirely incompatible with an abstract model of configuration, and thus is quite complex and awkward to implement in Puppet, requiring the proper relationship metaparameters for those commands.

With Otter, just add the "detach" operation at the beginning of the block and the "attach" operation at the end. By default, the block will run only if any of the "ensure" operations indicate configuration drift.

Change Management and Compliance

DevOps isn't only about faster cycles, it's about responsible cycles, which sometimes means process.

The idea of automatically remediating configuration drift is generally expected in a Linux Configuration Management tool, but can be a terrifying idea to governance and compliance personnel in enterprise organizations. Over the years, Puppet has struggled to balance these two mindsets.

Puppet used to offer a dedicated "compliance tool", but has since replaced it with the Compliance Alternate Workflow. It's a bit awkward to use:

  • Instead of running Puppet agent in its default mode, run it in "no op" mode, which causes Puppet to detect changes and simulate changes, without automatically enforcing the desired state
  • In the console, look for "pending" events and node status. "Pending" is how the console represents detected differences and simulated changes.
  • Run the agent in the default mode when you are ready to approve the changes

Compliance is built in to Otter. Servers can be configured to automatically remediate drift or simply report on it and give you the option to schedule a job to automatically remediate the drift. These are all first class concepts, as opposed to afterthoughts.

Puppet's DSL vs Otter Plans

Puppet is often criticized for having its own, domain specific language (DSL) for configuration management. According to PuppetLabs CEO Luke Kaines:

Most people love the language and find it the simplest way of expressing their configurations, but some are frustrated by how simple it is and wish they had a full Turing-complete language like Ruby for specification

PuppetScript is tightly coupled to its abstract configuration model, and although it has evolved over the years, procedural constructs like loops, conditionals, and error handling are awkward when compared with normal, procedural code. This is, understandably, where most of the frustration comes in.

Yet Another Language to Learn

Some critics have claimed that a DSL is "yet another language" to learn, thereby increasing the learning curve and organizational adoption. Otter's visual plan editor essentially flattens the learning curve; not just the Otter's DSL, but of the individual operations and their arguments.

Otter In Action

And because you can switch between visual- and text-modes, learning OtterScript and Otter is a easy.

PuppetScript vs OtterScript

Puppet was built for configuration management, and PuppetScript is a declarative language that describes configuration.

Otter, on the other hand, was built for infrastructure configuration and orchestration, and OtterScript is a procedural language that describes a declarative configuration plan or procedural orchestration plan.

Because of these fundamental differences, comparing the languages feature-for-feature is not all that helpful, although it is worth noting that OtterScript is much simpler than PuppetScript.

For example, unlike Puppet's Expressions, OtterScript literal expressions do not support arithmetic expressions, or anything other than variable expansion. While it may seem limiting, OtterScript instead relies on variable functions and tight scripting integration to accomplish effectively the same thing, using the method and language of your choice.

  • PuppetScript
  • OtterScript
$value = (48 + 1) /2 * 7
debug("The answer is ${value}") 
set $value = $PSEval((48 + 1) /2 * 7);
Log-Debug The answer is $value;

In the example above, PSEval is using PowerShell to evaluate the expression. If the relatively minor performance overhead of using the PowerShell runtime were to ever be a concern, then writing a $EvalMath variable function to parse and evaluate the expression would be quite easy.

Puppet Terminology vs Otter Terminology

If you're already familiar with Puppet, this will compare and contrast the terms used.

Puppet Otter Notes
Agent Agent Same, except Otter agents are used only for Windows servers
Catalog - Otter doesn't have a term for this, but this is accomplished as part of a routine configuration execution
Facts Configuration
Manifest Configuration Plan
Module Raft or Extension Highly reusable components are generally created as extensions, whereas bundled configuration is created as a raft
Node Server
Puppet master Otter server See Architecture & Components
Resource Operation or Asset