Permalink
Browse files

Update skeleton sinatra plugin

Modify the skeleton sinatra plugin to conform to the new staging
plugin changes.

Test plan:
- Unit tests
- Enabled the plugin on the stager, deployed the env app

Change-Id: Ic600bf710320dfef53c94539838aa49e79c15f12
  • Loading branch information...
1 parent c092a1d commit f78e2a480c70f101090e398d986c452ef633e1a8 mpage committed Nov 18, 2011
@@ -0,0 +1,4 @@
+---
+ruby_paths:
+ ruby18: ruby
+ ruby19: ruby
@@ -1,18 +1,4 @@
+#!/bin/bash
echo $$ > ./run.pid
-
-<% if uses_bundler %>
-
-export PATH="$PWD/app/rubygems/ruby/<%= library_version %>/bin:$PATH"
-export GEM_PATH="$PWD/app/rubygems/ruby/<%= library_version %>"
-export GEM_HOME="$PWD/app/rubygems/ruby/<%= library_version %>"
-export RUBYOPT="-I$PWD/ruby -rstdsync'"
-cd app
-exec ruby ./rubygems/ruby/<%= library_version %>/bin/bundle exec ruby ./<%= sinatra_main %> $@
-
-<% else %>
-
-export RUBYOPT="-rubygems -I$PWD/ruby -rstdsync"
-cd app
-exec ruby ./<%= sinatra_main %> $@
-
-<% end %>
+cd <%= app_dir %>
+exec <%= ruby_path %> <%= sinatra_main %> $@
@@ -0,0 +1,2 @@
+require 'vcap/plugins/staging/sinatra/plugin'
+require 'vcap/plugins/staging/sinatra/version'
@@ -0,0 +1,4 @@
+require 'vcap/plugin_registry'
+require 'vcap/plugins/staging/sinatra'
+
+VCAP::PluginRegistry.register_plugins(VCAP::Plugins::Staging::Sinatra.new)
@@ -0,0 +1,96 @@
+require 'erb'
+require 'fileutils'
+
+module VCAP
+ module Plugins
+ module Staging
+ end
+ end
+end
+
+class VCAP::Plugins::Staging::Sinatra
+ ASSET_DIR = File.expand_path('../../../../../../assets', __FILE__)
+ STDSYNC_PATH = File.join(ASSET_DIR, 'stdsync.rb')
+ START_TEMPLATE_PATH = File.join(ASSET_DIR, 'start.erb')
+ STOP_SCRIPT_PATH = File.join(ASSET_DIR, 'stop')
+ DEFAULT_CONFIG_PATH = File.join(ASSET_DIR, 'config.yml')
+ SINATRA_DETECTION_REGEX = /require 'sinatra'|require "sinatra"/
+
+ attr_reader :framework
+ attr_reader :name
+
+ def initialize(config_path=DEFAULT_CONFIG_PATH)
+ @framework = 'sinatra'
+ @name = 'vcap_sinatra_staging_plugin'
+ @ruby_paths = {}
+ @start_template = ERB.new(File.read(START_TEMPLATE_PATH))
+ configure(config_path)
+ end
+
+ def configure(config_path)
+ config = YAML.load_file(config_path)
+ @ruby_paths = config['ruby_paths']
+ unless @ruby_paths
+ raise "ruby_paths missing from config at #{config_path}"
+ end
+ end
+
+ def stage(app_root, actions, app_props)
+ sinatra_main = find_main_file(app_root)
+ unless sinatra_main
+ actions.abort_staging("Could not find main file in application root.")
+ end
+
+ ruby_path = @ruby_paths[app_props['runtime']]
+ unless ruby_path
+ actions.abort_staging("No ruby executable for runtime #{app_props['runtime']}")
+ end
+
+ actions.environment['RUBYOPT'] = '"-I$PWD/ruby -rstdsync"'
+ copy_stdsync(actions.droplet_base_dir)
+ generate_start_script(actions.start_script, File.basename(app_root), sinatra_main, ruby_path)
+ generate_stop_script(actions.stop_script)
+ end
+
+ # Finds the first file in the application root that requires sinatra.
+ #
+ # @param app_dir Path to the root of the application's source directory.
+ def find_main_file(app_dir)
+ for src_file in Dir.glob(File.join(app_dir, '*'))
+ src_contents = File.read(src_file)
+ return File.basename(src_file) if src_contents.match(SINATRA_DETECTION_REGEX)
+ end
+ nil
+ end
+
+ # The file stdsync.rb contains a single line that sets stdout to synchronous mode.
+ # The startup script we generate expects it to live at 'DROPLET_ROOT/ruby/stdsync.rb'.
+ # Make sure we put it there.
+ #
+ # @param base_dir String Path to the base of the droplet being created.
+ def copy_stdsync(base_dir)
+ stdsync_dir = File.join(base_dir, 'ruby')
+ stdsync_dst = File.join(stdsync_dir, 'stdsync.rb')
+ FileUtils.mkdir(stdsync_dir)
+ FileUtils.cp(STDSYNC_PATH, stdsync_dst)
+ end
+
+ # Generates the startup script that will be run on the DEA.
+ #
+ # @param start_script File Open file that will house the start script.
+ # @param app_dir String Basename of app dir relative to droplet root
+ # @param sinatra_main String Name of 'main' sinatra file.
+ # @param ruby_path String Path to ruby executable that should run the application
+ def generate_start_script(start_script, app_dir, sinatra_main, ruby_path)
+ contents = @start_template.result(binding())
+ start_script.write(contents)
+ end
+
+ # Writes out the stop script
+ #
+ # @param stop_script File Open file that will house the stop script
+ def generate_stop_script(stop_script)
+ contents = File.read(STOP_SCRIPT_PATH)
+ stop_script.write(contents)
+ end
+end
@@ -1,2 +0,0 @@
-require 'vcap/plugins/staging/sinatra_staging_plugin/plugin'
-require 'vcap/plugins/staging/sinatra_staging_plugin/version'
@@ -1,75 +0,0 @@
-require 'erb'
-require 'fileutils'
-
-module VCAP
- module Plugins
- module Staging
- class SinatraStagingPluginError < StandardError; end
- end
- end
-end
-
-class VCAP::Plugins::Staging::SinatraStagingPlugin
- ASSET_DIR = File.expand_path('../../../../../../assets', __FILE__)
- STDSYNC_PATH = File.join(ASSET_DIR, 'stdsync.rb')
- START_TEMPLATE_PATH = File.join(ASSET_DIR, 'start.erb')
- SINATRA_DETECTION_REGEX = /require 'sinatra'|require "sinatra"/
-
- attr_reader :name, :plugin_type
-
- def initialize
- @name = 'vcap_sinatra_plugin'
- @plugin_type = :framework
- end
-
- def stage(app_dir, actions, app_properties)
- sinatra_main = find_main_file(app_dir)
- raise VCAP::Plugins::Staging::SinatraStagingPluginError, "Couldn't find main file" unless sinatra_main
- copy_stdsync(actions.droplet_base_dir)
- generate_start_script(actions.start_script, app_dir, sinatra_main, app_properties)
- end
-
- private
-
- # Finds the first file in the application root that requires sinatra.
- #
- # @param app_dir Path to the root of the application's source directory.
- def find_main_file(app_dir)
- for src_file in Dir.glob(File.join(app_dir, '*'))
- src_contents = File.read(src_file)
- return File.basename(src_file) if src_contents.match(SINATRA_DETECTION_REGEX)
- end
- nil
- end
-
- # The file stdsync.rb contains a single line that sets stdout to synchronous mode.
- # The startup script we generate expects it to live at 'DROPLET_ROOT/ruby/stdsync.rb'.
- # Make sure we put it there.
- #
- # @param base_dir String Path to the base of the droplet being created.
- def copy_stdsync(base_dir)
- stdsync_dir = File.join(base_dir, 'ruby')
- stdsync_dst = File.join(stdsync_dir, 'stdsync.rb')
- FileUtils.mkdir(stdsync_dir)
- FileUtils.cp(STDSYNC_PATH, stdsync_dst)
- end
-
- # Generates the startup script that will be run on the DEA.
- #
- # @param start_script File Open file that will house the start script.
- # @param source_dir String Path to application source
- # @param sinatra_main String Name of 'main' sinatra file.
- # @param app_props VCAP::Stager::AppProperties Properties of app being staged.
- def generate_start_script(start_script, source_dir, sinatra_main, app_props)
- # Template vars
- if app_props.runtime == 'ruby19'
- library_version = '1.9.1'
- else
- library_version = '1.8'
- end
- uses_bundler = File.exists?(File.join(source_dir, 'Gemfile.lock'))
-
- template = ERB.new(File.read(START_TEMPLATE_PATH))
- start_script.write(template.result(binding))
- end
-end
@@ -2,9 +2,9 @@
require 'fileutils'
require 'tmpdir'
-require 'vcap/plugins/staging/sinatra_staging_plugin'
+require 'vcap/plugins/staging/sinatra'
-describe VCAP::Plugins::Staging::SinatraStagingPlugin do
+describe VCAP::Plugins::Staging::Sinatra do
TEST_ASSETS_DIR = File.expand_path('../../test_assets', __FILE__)
describe '#find_main_file' do
@@ -17,20 +17,20 @@
end
it 'should return nil if it cannot find a ruby file in the root directory that requires sinatra' do
- plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new
- plugin.send(:find_main_file, @tmpdir).should be_nil
+ plugin = VCAP::Plugins::Staging::Sinatra.new
+ plugin.find_main_file(@tmpdir).should be_nil
end
it 'should detect files that require sinatra using single quotes' do
copy_test_asset('sinatra_single_quotes.rb', @tmpdir)
- plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new
- plugin.send(:find_main_file, @tmpdir).should == 'sinatra_single_quotes.rb'
+ plugin = VCAP::Plugins::Staging::Sinatra.new
+ plugin.find_main_file(@tmpdir).should == 'sinatra_single_quotes.rb'
end
it 'should detect files that require sinatra using double quotes' do
copy_test_asset('sinatra_double_quotes.rb', @tmpdir)
- plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new
- plugin.send(:find_main_file, @tmpdir).should == 'sinatra_double_quotes.rb'
+ plugin = VCAP::Plugins::Staging::Sinatra.new
+ plugin.find_main_file(@tmpdir).should == 'sinatra_double_quotes.rb'
end
end
@@ -44,13 +44,13 @@
end
it 'should copy stdsync.rb to ruby/stdsync.rb in the droplet root' do
- plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new
- plugin.send(:copy_stdsync, @tmpdir)
+ plugin = VCAP::Plugins::Staging::Sinatra.new
+ plugin.copy_stdsync(@tmpdir)
File.exist?(File.join(@tmpdir, 'ruby', 'stdsync.rb')).should be_true
end
end
- describe '#generate_start_script' do
+ describe '#stage' do
before :each do
@tmpdir = Dir.mktmpdir
end
@@ -59,31 +59,23 @@
FileUtils.rm_rf(@tmpdir)
end
- # Not sure about the best way to test this. We're really just checking that
- # the correct block of the if statement is executed in the startup script template...
- it 'should use bundle to start the app if it includes a Gemfile.lock' do
- copy_test_asset('sinatra_single_quotes.rb', @tmpdir)
- File.open(File.join(@tmpdir, 'Gemfile.lock'), 'w+') {|f| f.write('foo') }
- plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new
- start_script = StringIO.new
- props = mock(:props)
- props.should_receive(:runtime).and_return('ruby19')
- plugin.send(:generate_start_script, start_script, @tmpdir, 'sinatra_single_quotes.rb', props)
- start_script.rewind
- script_contents = start_script.read
- script_contents.match('bundle exec').should be_true
+ it 'should call abort_staging if it cannot find the main file' do
+ plugin = VCAP::Plugins::Staging::Sinatra.new
+ actions = mock()
+ actions.should_receive(:abort_staging).with(any_args()).and_raise(RuntimeError.new)
+ expect do
+ plugin.stage(@tmpdir, actions, {'runtime' => 'ruby18'})
+ end.to raise_error
end
- it 'start the app directly if no Gemfile.lock is included' do
+ it 'should call abort_staging if it cannot find an executable for the supplied runtime' do
copy_test_asset('sinatra_single_quotes.rb', @tmpdir)
- plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new
- start_script = StringIO.new
- props = mock(:props)
- props.should_receive(:runtime).and_return('ruby19')
- plugin.send(:generate_start_script, start_script, @tmpdir, 'sinatra_single_quotes.rb', props)
- start_script.rewind
- script_contents = start_script.read
- script_contents.match('bundle exec').should be_false
+ plugin = VCAP::Plugins::Staging::Sinatra.new
+ actions = mock()
+ actions.should_receive(:abort_staging).with(any_args()).and_raise(RuntimeError.new)
+ expect do
+ plugin.stage(@tmpdir, actions, {'runtime' => 'invalid'})
+ end.to raise_error
end
end
@@ -1,6 +1,5 @@
-# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
-require "vcap/plugins/staging/sinatra_staging_plugin/version"
+require "vcap/plugins/staging/sinatra/version"
Gem::Specification.new do |s|
s.name = "vcap_sinatra_staging_plugin"
@@ -11,16 +10,11 @@ Gem::Specification.new do |s|
s.summary = %q{Stages sinatra applications for deployment in Cloud Foundry.}
s.description = %q{Modifies applications for deployment in CF.}
- s.rubyforge_project = "vcap_sinatra_staging_plugin"
-
s.files = %w(Rakefile Gemfile) + Dir.glob("{lib,spec,assets,test_assets}/**/*")
s.executables = []
s.bindir = 'bin'
s.require_paths = ["lib"]
- # XXX - These need to be development dependencies. Figure out why bundler isn't installing
- # them later...
- s.add_dependency("rspec")
- s.add_dependency("rspec-core")
- s.add_dependency("rake")
+ s.add_development_dependency("rspec")
+ s.add_development_dependency("rake")
end

0 comments on commit f78e2a4

Please sign in to comment.