Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Commit

Permalink
Update skeleton sinatra plugin
Browse files Browse the repository at this point in the history
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
mpage committed Nov 18, 2011
1 parent c092a1d commit f78e2a4
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 136 deletions.
4 changes: 4 additions & 0 deletions plugins/staging/sinatra/assets/config.yml
@@ -0,0 +1,4 @@
---
ruby_paths:
ruby18: ruby
ruby19: ruby
20 changes: 3 additions & 17 deletions plugins/staging/sinatra/assets/start.erb
@@ -1,18 +1,4 @@
#!/bin/bash
echo $$ > ./run.pid echo $$ > ./run.pid

cd <%= app_dir %>
<% if uses_bundler %> exec <%= ruby_path %> <%= sinatra_main %> $@

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 %>
2 changes: 2 additions & 0 deletions plugins/staging/sinatra/lib/vcap/plugins/staging/sinatra.rb
@@ -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)
96 changes: 96 additions & 0 deletions plugins/staging/sinatra/lib/vcap/plugins/staging/sinatra/plugin.rb
@@ -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

This file was deleted.

This file was deleted.

58 changes: 25 additions & 33 deletions plugins/staging/sinatra/spec/plugin_spec.rb
Expand Up @@ -2,9 +2,9 @@
require 'fileutils' require 'fileutils'
require 'tmpdir' 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__) TEST_ASSETS_DIR = File.expand_path('../../test_assets', __FILE__)


describe '#find_main_file' do describe '#find_main_file' do
Expand All @@ -17,20 +17,20 @@
end end


it 'should return nil if it cannot find a ruby file in the root directory that requires sinatra' do 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 = VCAP::Plugins::Staging::Sinatra.new
plugin.send(:find_main_file, @tmpdir).should be_nil plugin.find_main_file(@tmpdir).should be_nil
end end


it 'should detect files that require sinatra using single quotes' do it 'should detect files that require sinatra using single quotes' do
copy_test_asset('sinatra_single_quotes.rb', @tmpdir) copy_test_asset('sinatra_single_quotes.rb', @tmpdir)
plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new plugin = VCAP::Plugins::Staging::Sinatra.new
plugin.send(:find_main_file, @tmpdir).should == 'sinatra_single_quotes.rb' plugin.find_main_file(@tmpdir).should == 'sinatra_single_quotes.rb'
end end


it 'should detect files that require sinatra using double quotes' do it 'should detect files that require sinatra using double quotes' do
copy_test_asset('sinatra_double_quotes.rb', @tmpdir) copy_test_asset('sinatra_double_quotes.rb', @tmpdir)
plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new plugin = VCAP::Plugins::Staging::Sinatra.new
plugin.send(:find_main_file, @tmpdir).should == 'sinatra_double_quotes.rb' plugin.find_main_file(@tmpdir).should == 'sinatra_double_quotes.rb'
end end
end end


Expand All @@ -44,13 +44,13 @@
end end


it 'should copy stdsync.rb to ruby/stdsync.rb in the droplet root' do it 'should copy stdsync.rb to ruby/stdsync.rb in the droplet root' do
plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new plugin = VCAP::Plugins::Staging::Sinatra.new
plugin.send(:copy_stdsync, @tmpdir) plugin.copy_stdsync(@tmpdir)
File.exist?(File.join(@tmpdir, 'ruby', 'stdsync.rb')).should be_true File.exist?(File.join(@tmpdir, 'ruby', 'stdsync.rb')).should be_true
end end
end end


describe '#generate_start_script' do describe '#stage' do
before :each do before :each do
@tmpdir = Dir.mktmpdir @tmpdir = Dir.mktmpdir
end end
Expand All @@ -59,31 +59,23 @@
FileUtils.rm_rf(@tmpdir) FileUtils.rm_rf(@tmpdir)
end end


# Not sure about the best way to test this. We're really just checking that it 'should call abort_staging if it cannot find the main file' do
# the correct block of the if statement is executed in the startup script template... plugin = VCAP::Plugins::Staging::Sinatra.new
it 'should use bundle to start the app if it includes a Gemfile.lock' do actions = mock()
copy_test_asset('sinatra_single_quotes.rb', @tmpdir) actions.should_receive(:abort_staging).with(any_args()).and_raise(RuntimeError.new)
File.open(File.join(@tmpdir, 'Gemfile.lock'), 'w+') {|f| f.write('foo') } expect do
plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new plugin.stage(@tmpdir, actions, {'runtime' => 'ruby18'})
start_script = StringIO.new end.to raise_error
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
end 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) copy_test_asset('sinatra_single_quotes.rb', @tmpdir)
plugin = VCAP::Plugins::Staging::SinatraStagingPlugin.new plugin = VCAP::Plugins::Staging::Sinatra.new
start_script = StringIO.new actions = mock()
props = mock(:props) actions.should_receive(:abort_staging).with(any_args()).and_raise(RuntimeError.new)
props.should_receive(:runtime).and_return('ruby19') expect do
plugin.send(:generate_start_script, start_script, @tmpdir, 'sinatra_single_quotes.rb', props) plugin.stage(@tmpdir, actions, {'runtime' => 'invalid'})
start_script.rewind end.to raise_error
script_contents = start_script.read
script_contents.match('bundle exec').should be_false
end end
end end


Expand Down
12 changes: 3 additions & 9 deletions plugins/staging/sinatra/vcap_sinatra_staging_plugin.gemspec
@@ -1,6 +1,5 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__) $:.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| Gem::Specification.new do |s|
s.name = "vcap_sinatra_staging_plugin" s.name = "vcap_sinatra_staging_plugin"
Expand All @@ -11,16 +10,11 @@ Gem::Specification.new do |s|
s.summary = %q{Stages sinatra applications for deployment in Cloud Foundry.} s.summary = %q{Stages sinatra applications for deployment in Cloud Foundry.}
s.description = %q{Modifies applications for deployment in CF.} 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.files = %w(Rakefile Gemfile) + Dir.glob("{lib,spec,assets,test_assets}/**/*")
s.executables = [] s.executables = []
s.bindir = 'bin' s.bindir = 'bin'
s.require_paths = ["lib"] s.require_paths = ["lib"]


# XXX - These need to be development dependencies. Figure out why bundler isn't installing s.add_development_dependency("rspec")
# them later... s.add_development_dependency("rake")
s.add_dependency("rspec")
s.add_dependency("rspec-core")
s.add_dependency("rake")
end end

0 comments on commit f78e2a4

Please sign in to comment.