Skip to content

Instantly share code, notes, and snippets.

@clowder
Created January 18, 2012 17:28
Show Gist options
  • Save clowder/1634277 to your computer and use it in GitHub Desktop.
Save clowder/1634277 to your computer and use it in GitHub Desktop.
Creating custom exporters for Foreman

Creating custom exporters for Foreman

Creating the exporter

To start with you should subclass [Foreman::Export::Base] and your subclass should exist within the [Foreman::Export] namespace.

class Foreman::Export::MyRunitExporter < Foreman::Export::Base
end

Then the only method that you need to implement on your class is the [Foreman::Export::MyRunitExporter#export] method (it is passed no arguments).

class Foreman::Export::MyRunitExporter < Foreman::Export::Base
  def export
    error("Must specify a location") unless location

    @location = Pathname.new(@location)

    engine.procfile.entries.each do |process|
      1.upto(self.concurrency[process.name]) do |num|
        service_name          = "#{app}-#{process.name}-#{num}"
        port                  = engine.port_for(process, num, self.port)
        environment_variables = {'PORT' => port}.merge(engine.environment)

        service = Service.new(service_name, process.command, location, environment_variables)

        service.create!
        service.activate!
      end
    end
  end
End

From your subclass you have access to the following attr_reader’s.

  • location: Where the user wants you to place the files
  • engine: The [Foreman::Engine] for the current application
  • app: The command line option --app
  • log: The command line option --log
  • port: The command line option --port
  • user: The command line option --user
  • template: The command line option --template

You should make sure that your a good citizen and respect all of Foremans user configurable options!

Ensuring that your exporter will load

Foreman follows Rails-ish conventions (‘dasherizing', ‘underscoring' and ‘classifying’) when it comes to loading your custom exporters. So continuing our example from above we should invoke our custom exporter using a ‘dasherized’ version of the classname with something like...

be foreman export my-runit-exporter ~/etc/sv/ --app my-application

Foreman will attempt to require foreman/export/my_runit_exporter and will call you class as expected.

More info

To view a full working exporter (as a gem) there is an example over at nature/foreman-export-nature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment