Skip to main content

Defining an application model

As of today, users can create applications in ShapeBlock only via the UI.

Create a new app in ShapeBlock

This defeats the whole point of “infrastructure-as-code”. I want to have a specification file in my source code which defines the following traits of an application, like:

  • what platform is the application(ex. PHP, Python)
  • what version of the platform(ex. PHP 7.4, Python 3.9 etc)
  • how to build this application(are we going to use a dependency manager like Pip)
  • setting environment variables for your application
  • what disk volumes to persist between application redeployment
  • Are we running any background worker processes.(ex. Celery tasks, Sidekiq).

Why have an application model? #

We need an application model to be codified for 3 reasons. First, it gives us a clear specification of what our application will look like. This makes it easier to repeat or copy the same spec for another application. Second, an application specification gives a predictable checklist of what is possible and what’s not. In the absence of a specification, it is hard to diagnose and debug what’s wrong when the application fails to deploy on a platform. Finally, a specification forces us to adopt a standard for defining applications, irrespective of the platform or the underlying infrastructure. This facilitates for more portability or interoperability across different platforms. Which brings us to my next topic, existing application standards.

What is already out there? #

I evaluated application models on 3 platforms I’ve used previously.

Heroku app model #

This is JSON based. Not a big turn-off for me. But JSON makes writing multi-line configuration clumsy. Not to mention lot of Heroku-ish elements in the configuration, like addons.

DigitalOcean app model #

This is relatively new kid in the block. First off, it is YAML, which is a relief. It contains a lot of goodies, like health check and alerts. It also contains implementation details like “dockerfile path”. Currently, we’re “buildpack only”. So, will be weeding this out. Also, there is a separate section called “functions”. This is intended for running FaaS. There is no way in this model, for example, to specify a composer private repository while building a PHP application. At least at the time of writing this.

Platform.sh model #

I’ve been a platform.sh fanboy for longer than I care to admit. I like most of their app model. It ticks all boxes. But I believe they’ve abstracted it a tad too much. Instead of allowing people to write raw Nginx config, they define a set of YAML rules. Here’s an instance for a Drupal application:

web:
    locations:
        # All requests not otherwise specified follow these rules.
        '/':
            # The folder from which to serve static assets, for this location.
            #
            # This is a filesystem path, relative to the application root.
            root: 'web'

            # How long to allow static assets from this location to be cached.
            #
            # Can be a time in seconds, or -1 for no caching. Times can be
            # suffixed with "s" (seconds), "m" (minutes), "h" (hours), "d"
            # (days), "w" (weeks), "M" (months, as 30 days) or "y" (years, as
            # 365 days).
            expires: 5m

            # Redirect any incoming request to Drupal's front controller.
            passthru: '/index.php'

            # Deny access to all static files, except those specifically allowed below.
            allow: false

            # Rules for specific URI patterns.
            rules:
                # Allow access to common static files.
                '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$':
                    allow: true
                '^/robots\.txt$':
                    allow: true
                '^/sitemap\.xml$':
                    allow: true

                # Deny direct access to configuration files.
                '^/sites/sites\.php$':
                    scripts: false
                '^/sites/[^/]+/settings.*?\.php$':
                    scripts: false

Their intention is to prevent people from shooting in the foot by writing incorrect nginx configuration. I’m more comfortable writing this as Nginx rather than writing a YAML abstraction and hoping that it translates exactly into what I want. Also, they move services and routes to a different file. I can’t fathom why that would be the case. Other than that, this app model feels just fine.

Open application model #

This strives to be the grand unified model of all applications. But some of the items listed in my wishlist are not part of their goals. There is a lot of emphasis on “Deploying” an application, and very little emphasis on “Building” an application. I found it hard to relate as there were no practical examples, in the sense of “Here’s you Java application, here’s your OAM YAML for this application.”

I ended up picking a variation of the platform.sh specification, with some changes.

  1. Process is defined by Procfile. This doesn’t exist in Platform.sh model.
  2. Nginx configuraion is part of the code base and explicit.
  3. pre-deploy and post-deploy commands are explicit script files as part of the code base.

The end goal is as little magic as possible, while being consistent and to-the-extent-possible stick to “infrastructure as code” principles.