Ruby Library for the Stager API

Apcera stagers let you create and manage your organization's life-cycle management processes. Stagers run as jobs, and you can write them in any language you wish. They are run via staging pipelines, which execute stagers in a given order. Apcera provides a number of built-in staging pipelines to deploy common application workloads.

The HTTP-based Stager API lets you create custom stagers. To make the Stager API easier to use, Apcera also provides a Ruby library that wraps HTTP calls to the Stager API in a small set of methods. This article describes how to use the Ruby library to create a custom stager.

Basic usage

This section describes the basic process for creating a custom stager using the Ruby library, creating a staging pipeline from it, and using the staging pipeline to stage an application. For a complete working example, see Sample stager.

To configure your environment, create a Gemfile with the following contents:

source "https://rubygems.org"
gem "apcera-stager-api"

Then run bundle install to download and install the gem and its dependencies:

bundle install

Now that your environment is set up, you can create a new file for your stager (Apcera recommends you name the file "stager.rb"). The following code illustrates the core functionality provided by the Ruby library: downloading and extracting the application package (source code), compressing and uploading the modified package contents to the staging coordinator. You provide the custom logic to prepare the package for execution, such as compiling code, installing dependencies, or setting environment variables.

#!/usr/bin/env ruby

require "bundler"
Bundler.setup

require "apcera-stager-api"

stager = Apcera::Stager.new

# Download the package from the staging coordinator.
# This is the code that requires staging!
puts "Downloading Package..."
stager.download

# Extract the package to the `app` directory.
puts "Extracting Package..."
stager.extract(`app`)

# Your custom staging logic goes here - A set of commands
# to execute in order to stage your applications.

# Finish staging, this uploads the final package to the
# staging coordinator.
puts "Completed Staging..."
stager.complete

Make sure stager.rb is executable:

chmod +x stager.rb

Deploy the new stager and create a staging pipeline from it:

apc stager create mystager --start-command="./stager.rb" --staging=/apcera::ruby --pipeline

Deploy an app using mystager:

apc app create someapp --staging=mystager

Method reference

The following table lists the methods provided by the Ruby library. See the sample stager application for examples of some of these methods.

Method Arguments Operation
complete none Convenience method that wraps a call to upload followed by done.
dependencies_add type, name Adds a package to the app's list of dependencies. Returns a boolean that indicates if the specified package is already in the app list of dependencies (false) or not (true). If true is returned, the stager must call the library's relaunch method. See Relaunching a Stager in the Stager API documentation for more information.
dependencies_remove type, name Removes a package from the app's list of dependencies. Returns a boolean that indicates if the specified package needed to be removed (true) or not (false). If true is returned, the stager must call the library's relaunch method. See Relaunching a Stager in the Stager API documentation for more information.
done   Informs the staging coordinator that the stager is done.
download   Downloads contents of the package from the staging coordinator, and saves it to pkg.tar.gz.
environment_add name, value Adds an environment variable for the app's use.
environment_remove name Removes an environment variable from the app.
execute command Executes command in the current directory with a clean working environment
execute_app command Execute command in the app directory with a clean working environment
extract path – Path to directory in which to extract the package contents. Extracts the package contents to the specified path.
fail   Returns from the stager with an exit code of 1, and sends an error message to stderr.
initialize from STAGER_URL environment variable Creates a new stager and gives it the URL of its staging coordinator.
meta   Returns metadata about the app in JSON format from the staging coordinator.
output text Sends text to stdout.
output_error text Sends text to stderr.
provides_add type, name Adds to the list of capabilities that the app provides.
provides_remove type, name Removes from the list of capabilities that the app provides.
relaunch   Tells the staging coordinator to restart the staging process; necessary when the application's dependencies change (see Relaunching a Stager).
snapshot   Updates the package with a snapshot of the stager's file system.
start_command (set) command Sets the app's start command to command.
start_command (get)   Gets the start command for the app.
start_path (set) path Sets the app's start path to path.
start_path (get)   Gets the start path for the app.
templates_add path, left_delimiter, right_delimiter Adds a runtime template located at the specified path to the app, optionally specifying the left and right delimiters used by the template. By default, the left and right delimiters are {{ and }}.
templates_remove path, left_delimiter, right_delimiter Removes a runtime template located at the specified path from the app, optionally specifying the left and right delimiters used by the template. By default, the left and right delimiters are {{ and }}.
upload   Compresses the app directory and its subdirectories into a new package and sends it to the staging coordinator.

Example stager

The example-apcera-stager-api sample implements a custom stager for Sinatra applications. The complete code listing for the stager is shown below. It performs the following steps:

  • Adds Ruby as a dependency to the stager.
  • Sets the application's start command and start path.
  • Adds an environment variable to the application.
  • Downloads and extracts the application package (source code to deploy) and runs bundle install on its contents.
  • Uploads the modified package to the staging coordinator.

#!/usr/bin/env ruby

# Simple sinatra stager.

require "bundler"
Bundler.setup

# Bring in apcera-stager-api
require "apcera-stager-api"

# Make sure stdout is sync'd.
STDOUT.sync = true

stager = Apcera::Stager.new

# Add the ruby dependency we need to stage our app. If it was added
# then restart the stager, otherwise we already have it.
puts "Adding ruby dependency"
should_restart = stager.dependencies_add("runtime", "ruby")
if should_restart == true
  stager.relaunch
end

# Set the start command.
start_cmd = "bundle exec rackup config.ru -p $PORT"
puts "Setting start command to '#{start_cmd}'"
stager.start_command = start_cmd

# Set the start path.
start_path = "/app"
puts "Setting start path to '#{start_path}'"
stager.start_path = start_path

# Make sure we're running in production mode.
puts "Setting RACK_ENV to production"
stager.environment_add("RACK_ENV", "production")

# Download the package from the staging coordinator.
puts "Downloading Package..."
stager.download

# Extract the package to the "app" directory.
puts "Extracting Package..."
stager.extract("app")

# Run bundler for my app in the extracted directory.
puts "Running Bundler..."
stager.execute_app("bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment")

# Finish staging, this will upload your final package to the
# staging coordinator.
puts "Completed Staging..."
stager.complete

To deploy and use the sample stager:

  1. Clone the sample-apps repository if you haven't already, or download and extract the ZIP.

  2. In a terminal, change to the sample-apps/example-apcera-stager-api directory:

     cd ~/sample-apps/example-apcera-stager-api/
    
  3. Deploy the custom stager and automatically create a staging pipeline for it:

     apc stager create myrubystager --start-command="./stager.rb" --staging=/apcera::ruby --pipeline --allow-egress
    

    The --allow-egress option permits the stager to access the external repositories to install dependencies. The start command specifies the stager.rb file that contains the stager logic.

  4. Deploy the demo-ruby-sinatra application in the sample-apps repo using the new staging pipeline:

     cd ~/sample-apps/demo-ruby-sinatra
     apc app create my-sinatra-app --staging=myrubystager --start
    

    You can now run the deployed Sinatra application at the URL route generated for you.