engineyard-serverside-adapter 1.3.1.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +9 -0
- data/engineyard-serverside-adapter.gemspec +25 -0
- data/lib/engineyard-serverside-adapter.rb +53 -0
- data/lib/engineyard-serverside-adapter/action.rb +94 -0
- data/lib/engineyard-serverside-adapter/arguments.rb +61 -0
- data/lib/engineyard-serverside-adapter/command.rb +66 -0
- data/lib/engineyard-serverside-adapter/deploy.rb +25 -0
- data/lib/engineyard-serverside-adapter/disable_maintenance_page.rb +19 -0
- data/lib/engineyard-serverside-adapter/enable_maintenance_page.rb +19 -0
- data/lib/engineyard-serverside-adapter/integrate.rb +21 -0
- data/lib/engineyard-serverside-adapter/rollback.rb +21 -0
- data/lib/engineyard-serverside-adapter/version.rb +7 -0
- data/spec/adapter_spec.rb +125 -0
- data/spec/arguments_spec.rb +28 -0
- data/spec/deploy_spec.rb +48 -0
- data/spec/disable_maintenance_page_spec.rb +26 -0
- data/spec/enable_maintenance_page_spec.rb +28 -0
- data/spec/integrate_spec.rb +32 -0
- data/spec/rollback_spec.rb +34 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +182 -0
- metadata +156 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/engineyard-serverside-adapter/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "engineyard-serverside-adapter"
|
6
|
+
s.version = EY::Serverside::Adapter::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = []
|
9
|
+
s.email = []
|
10
|
+
s.homepage = "http://github.com/engineyard/engineyard-serverside-adapter"
|
11
|
+
s.summary = "Adapter for speaking to engineyard-serverside"
|
12
|
+
s.description = "A separate adapter for speaking the CLI language of the engineyard-serverside gem."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "engineyard-serverside-adapter"
|
16
|
+
|
17
|
+
s.add_dependency "escape", "~> 0.0.4"
|
18
|
+
s.add_dependency "json_pure", "~> 1.4.6"
|
19
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
20
|
+
s.add_development_dependency "rspec", "~> 1.3.0"
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
24
|
+
s.require_path = 'lib'
|
25
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module EY
|
4
|
+
module Serverside
|
5
|
+
class Adapter
|
6
|
+
autoload :Action, 'engineyard-serverside-adapter/action'
|
7
|
+
autoload :Arguments, 'engineyard-serverside-adapter/arguments'
|
8
|
+
autoload :Command, 'engineyard-serverside-adapter/command'
|
9
|
+
autoload :Deploy, 'engineyard-serverside-adapter/deploy'
|
10
|
+
autoload :DisableMaintenancePage, 'engineyard-serverside-adapter/disable_maintenance_page'
|
11
|
+
autoload :EnableMaintenancePage, 'engineyard-serverside-adapter/enable_maintenance_page'
|
12
|
+
autoload :Integrate, 'engineyard-serverside-adapter/integrate'
|
13
|
+
autoload :Rollback, 'engineyard-serverside-adapter/rollback'
|
14
|
+
autoload :VERSION, 'engineyard-serverside-adapter/version'
|
15
|
+
|
16
|
+
ENGINEYARD_SERVERSIDE_VERSION = ENV['ENGINEYARD_SERVERSIDE_VERSION'] || VERSION
|
17
|
+
|
18
|
+
def initialize(gem_bin_path = "")
|
19
|
+
@gem_bin_path = Pathname.new(gem_bin_path)
|
20
|
+
@arguments = Arguments.new
|
21
|
+
|
22
|
+
yield @arguments if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def deploy(&b)
|
26
|
+
Deploy.new(new_action_args, &b)
|
27
|
+
end
|
28
|
+
|
29
|
+
def disable_maintenance_page(&b)
|
30
|
+
DisableMaintenancePage.new(new_action_args, &b)
|
31
|
+
end
|
32
|
+
|
33
|
+
def enable_maintenance_page(&b)
|
34
|
+
EnableMaintenancePage.new(new_action_args, &b)
|
35
|
+
end
|
36
|
+
|
37
|
+
def integrate(&b)
|
38
|
+
Integrate.new(new_action_args, &b)
|
39
|
+
end
|
40
|
+
|
41
|
+
def rollback(&b)
|
42
|
+
Rollback.new(new_action_args, &b)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def new_action_args
|
48
|
+
{:arguments => @arguments.dup, :gem_bin_path => @gem_bin_path}
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'escape'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module EY
|
5
|
+
module Serverside
|
6
|
+
class Adapter
|
7
|
+
class Action
|
8
|
+
|
9
|
+
def initialize(options = {}, &block)
|
10
|
+
@gem_bin_path = Pathname.new(options[:gem_bin_path] || "")
|
11
|
+
arguments = options[:arguments] || Arguments.new
|
12
|
+
block.call arguments if block
|
13
|
+
|
14
|
+
extract_state_from_arguments(arguments)
|
15
|
+
validate!
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(&block)
|
19
|
+
block.call check_and_install_command.to_s
|
20
|
+
block.call action_command.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def verbose
|
24
|
+
@state[:verbose]
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
attr_accessor :options
|
29
|
+
|
30
|
+
def option(name, type, extra={:required => false})
|
31
|
+
self.options ||= {}
|
32
|
+
options[name] = extra.merge({:type => type})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def extract_state_from_arguments(arguments)
|
39
|
+
@state = self.class.options.inject({}) do |acc, (option_name, option_attrs)|
|
40
|
+
acc.merge(option_name => arguments.send(option_name))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_and_install_command
|
45
|
+
"(#{check_command}) || (#{install_command})"
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_command
|
49
|
+
escaped_engineyard_serverside_version = ENGINEYARD_SERVERSIDE_VERSION.gsub(/\./, '\.')
|
50
|
+
|
51
|
+
[
|
52
|
+
Escape.shell_command([gem_path, "list", "engineyard-serverside"]),
|
53
|
+
Escape.shell_command(["grep", "engineyard-serverside "]),
|
54
|
+
Escape.shell_command(["egrep", "-q", "#{escaped_engineyard_serverside_version}[,)]"]),
|
55
|
+
].join(" | ")
|
56
|
+
end
|
57
|
+
|
58
|
+
def install_command
|
59
|
+
# rubygems looks at *.gem in its current directory for
|
60
|
+
# installation candidates, so we have to make sure it
|
61
|
+
# runs from a directory with no gem files in it.
|
62
|
+
#
|
63
|
+
# rubygems help suggests that --remote will disable this
|
64
|
+
# behavior, but it doesn't.
|
65
|
+
install_command = "cd `mktemp -d` && #{gem_path} install engineyard-serverside --no-rdoc --no-ri -v #{ENGINEYARD_SERVERSIDE_VERSION}"
|
66
|
+
Escape.shell_command(['sudo', 'sh', '-c', install_command])
|
67
|
+
end
|
68
|
+
|
69
|
+
def gem_path
|
70
|
+
@gem_bin_path.join('gem').to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
def action_command
|
74
|
+
cmd = Command.new(@gem_bin_path, *task)
|
75
|
+
@state.each do |option_name, value|
|
76
|
+
option_type = self.class.options[option_name][:type]
|
77
|
+
switch = "--" + option_name.to_s.gsub(/_/, '-')
|
78
|
+
cmd.send("#{option_type}_argument", switch, value)
|
79
|
+
end
|
80
|
+
cmd
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate!
|
84
|
+
self.class.options.each do |option_name, option_attrs|
|
85
|
+
if option_attrs[:required] && !@state[option_name]
|
86
|
+
raise ArgumentError, "Required field '#{option_name}' not provided."
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Adapter
|
4
|
+
class Arguments < Struct.new(:app, :config, :framework_env, :instances, :migrate, :ref, :repo, :stack, :verbose)
|
5
|
+
|
6
|
+
def app=(app)
|
7
|
+
enforce_nonempty!('app', app)
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def framework_env=(framework_env)
|
12
|
+
enforce_nonempty!('framework_env', framework_env)
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def instances=(instances)
|
17
|
+
unless instances.respond_to?(:each)
|
18
|
+
raise ArgumentError, "Value for 'instances' must look like an enumerable."
|
19
|
+
end
|
20
|
+
|
21
|
+
if instances.empty?
|
22
|
+
raise ArgumentError, "Value for 'instances' must not be empty."
|
23
|
+
end
|
24
|
+
|
25
|
+
instances.each do |instance|
|
26
|
+
unless instance.respond_to?(:[]) && instance[:hostname] && instance[:roles]
|
27
|
+
raise ArgumentError, "Malformed instance #{instance}; it must have both [:hostname] and [:roles]"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def ref=(ref)
|
35
|
+
enforce_nonempty!('ref', ref)
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def repo=(repo)
|
40
|
+
enforce_nonempty!('repo', repo)
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
def stack=(stack)
|
45
|
+
enforce_nonempty!('stack', stack)
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def enforce_nonempty!(name, value)
|
52
|
+
if value.to_s.empty?
|
53
|
+
raise ArgumentError, "Value for '#{name}' must be non-empty."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'escape'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module EY
|
5
|
+
module Serverside
|
6
|
+
class Adapter
|
7
|
+
class Command
|
8
|
+
def initialize(bin_path, *task)
|
9
|
+
@task = task
|
10
|
+
@arguments = []
|
11
|
+
@binary = bin_path.join('engineyard-serverside').to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
Escape.shell_command [@binary, "_#{ENGINEYARD_SERVERSIDE_VERSION}_"] + @task + @arguments.sort_by { |x| x.first }.flatten
|
16
|
+
end
|
17
|
+
|
18
|
+
def array_argument(switch, values)
|
19
|
+
compacted = values.compact.sort
|
20
|
+
if compacted.any?
|
21
|
+
@arguments << [switch, compacted]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def boolean_argument(switch, value)
|
26
|
+
if value
|
27
|
+
@arguments << [switch]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def hash_argument(switch, pairs)
|
32
|
+
if pairs.any? {|k,v| !v.nil?}
|
33
|
+
@arguments << [switch, pairs.reject { |k,v| v.nil? }.map { |pair| pair.join(':') }.sort]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def instances_argument(_, instances)
|
38
|
+
role_pairs = instances.inject({}) do |roles, instance|
|
39
|
+
roles.merge(instance[:hostname] => instance[:roles].join(','))
|
40
|
+
end
|
41
|
+
hash_argument('--instance-roles', role_pairs)
|
42
|
+
|
43
|
+
role_pairs = instances.inject({}) do |roles, instance|
|
44
|
+
roles.merge(instance[:hostname] => instance[:name])
|
45
|
+
end
|
46
|
+
hash_argument('--instance-names', role_pairs)
|
47
|
+
|
48
|
+
array_argument('--instances', instances.map{|i| i[:hostname]})
|
49
|
+
end
|
50
|
+
|
51
|
+
def json_argument(switch, value)
|
52
|
+
if value
|
53
|
+
string_argument(switch, value.to_json)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def string_argument(switch, value)
|
58
|
+
unless value.to_s.empty?
|
59
|
+
@arguments << [switch, value]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Adapter
|
4
|
+
class Deploy < Action
|
5
|
+
|
6
|
+
option :app, :string, :required => true
|
7
|
+
option :stack, :string, :required => true
|
8
|
+
option :instances, :instances, :required => true
|
9
|
+
option :config, :json
|
10
|
+
option :verbose, :boolean
|
11
|
+
option :framework_env, :string, :required => true
|
12
|
+
option :ref, :string, :required => true
|
13
|
+
option :repo, :string, :required => true
|
14
|
+
option :migrate, :string
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def task
|
19
|
+
['deploy']
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Adapter
|
4
|
+
class DisableMaintenancePage < Action
|
5
|
+
|
6
|
+
option :app, :string, :required => true
|
7
|
+
option :instances, :instances, :required => true
|
8
|
+
option :verbose, :boolean
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def task
|
13
|
+
['deploy', 'disable_maintenance_page']
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Adapter
|
4
|
+
class EnableMaintenancePage < Action
|
5
|
+
|
6
|
+
option :app, :string, :required => true
|
7
|
+
option :instances, :instances, :required => true
|
8
|
+
option :verbose, :boolean
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def task
|
13
|
+
['deploy', 'enable_maintenance_page']
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Adapter
|
4
|
+
class Integrate < Action
|
5
|
+
|
6
|
+
option :app, :string, :required => true
|
7
|
+
option :stack, :string, :required => true
|
8
|
+
option :instances, :instances, :required => true
|
9
|
+
option :framework_env, :string, :required => true
|
10
|
+
option :verbose, :boolean
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def task
|
15
|
+
['integrate']
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Adapter
|
4
|
+
class Rollback < Action
|
5
|
+
|
6
|
+
option :app, :string, :required => true
|
7
|
+
option :stack, :string, :required => true
|
8
|
+
option :instances, :instances, :required => true
|
9
|
+
option :config, :json
|
10
|
+
option :verbose, :boolean
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def task
|
15
|
+
['deploy', 'rollback']
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for "a serverside action" do
|
4
|
+
before(:each) do
|
5
|
+
@adapter = described_class.new do |args|
|
6
|
+
args.app = 'app-from-adapter-new'
|
7
|
+
args.instances = [{:hostname => 'localhost', :roles => %w[a b c]}]
|
8
|
+
args.framework_env = 'production'
|
9
|
+
args.ref = 'master'
|
10
|
+
args.repo = 'git@github.com:engineyard/engineyard-serverside.git'
|
11
|
+
args.stack = 'nginx_unicorn'
|
12
|
+
args
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "gives you an Arguments already set up from when you instantiated the adapter" do
|
17
|
+
command = @adapter.send(@method) do |args|
|
18
|
+
args.app.should == 'app-from-adapter-new'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "applies both sets of changes" do
|
23
|
+
action = @adapter.send(@method) do |args|
|
24
|
+
args.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
command = last_command(action)
|
28
|
+
command.should include('--app app-from-adapter-new')
|
29
|
+
command.should include('--verbose')
|
30
|
+
end
|
31
|
+
|
32
|
+
it "does not let arguments changes propagate back up to the adapter" do
|
33
|
+
command1 = @adapter.send(@method) do |args|
|
34
|
+
args.app = 'sporkr'
|
35
|
+
end
|
36
|
+
|
37
|
+
@adapter.send(@method) do |args|
|
38
|
+
args.app.should == 'app-from-adapter-new'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with no pathname specified" do
|
43
|
+
it "begins both commands with no path" do
|
44
|
+
action = @adapter.send(@method) do |args|
|
45
|
+
args.verbose = true
|
46
|
+
end
|
47
|
+
|
48
|
+
commands = all_commands(action)
|
49
|
+
commands.first.should =~ /^\(gem/
|
50
|
+
commands.last.should =~ /^engineyard-serverside/
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with a pathname specified" do
|
55
|
+
it "begins both commands with the given path" do
|
56
|
+
adapter = described_class.new("/usr/local/grin") do |args|
|
57
|
+
args.app = 'app-from-adapter-new'
|
58
|
+
args.instances = [{:hostname => 'localhost', :roles => %w[a b c]}]
|
59
|
+
args.framework_env = 'production'
|
60
|
+
args.ref = 'master'
|
61
|
+
args.repo = 'git@github.com:engineyard/engineyard-serverside.git'
|
62
|
+
args.stack = 'nginx_unicorn'
|
63
|
+
args
|
64
|
+
end
|
65
|
+
|
66
|
+
action = adapter.send(@method) do |args|
|
67
|
+
args.verbose = true
|
68
|
+
end
|
69
|
+
|
70
|
+
commands = all_commands(action)
|
71
|
+
commands.first.should =~ %r{^\(/usr/local/grin/gem}
|
72
|
+
commands.last.should =~ %r{^/usr/local/grin/engineyard-serverside}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe EY::Serverside::Adapter do
|
78
|
+
context ".new" do
|
79
|
+
it "lets you access the arguments" do
|
80
|
+
adapter = described_class.new do |args|
|
81
|
+
args.app = 'myapp'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "does not require a block" do
|
86
|
+
lambda { described_class.new }.should_not raise_error
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
[
|
91
|
+
:deploy,
|
92
|
+
:disable_maintenance_page,
|
93
|
+
:enable_maintenance_page,
|
94
|
+
:integrate,
|
95
|
+
:rollback,
|
96
|
+
].each do |method|
|
97
|
+
context "##{method}" do
|
98
|
+
before { @method = method }
|
99
|
+
it_should_behave_like "a serverside action"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "mapping of methods to action classes" do
|
104
|
+
before(:each) do
|
105
|
+
@adapter = described_class.new do |args|
|
106
|
+
args.app = 'app-from-adapter-new'
|
107
|
+
args.instances = [{:hostname => 'localhost', :roles => %w[a b c]}]
|
108
|
+
args.framework_env = 'production'
|
109
|
+
args.ref = 'master'
|
110
|
+
args.repo = 'git@github.com:engineyard/engineyard-serverside.git'
|
111
|
+
args.stack = 'nginx_unicorn'
|
112
|
+
args
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it "gives you the right command" do
|
117
|
+
@adapter.enable_maintenance_page.should be_kind_of(EY::Serverside::Adapter::EnableMaintenancePage)
|
118
|
+
@adapter.disable_maintenance_page.should be_kind_of(EY::Serverside::Adapter::DisableMaintenancePage)
|
119
|
+
@adapter.deploy.should be_kind_of(EY::Serverside::Adapter::Deploy)
|
120
|
+
@adapter.integrate.should be_kind_of(EY::Serverside::Adapter::Integrate)
|
121
|
+
@adapter.rollback.should be_kind_of(EY::Serverside::Adapter::Rollback)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Serverside::Adapter::Arguments do
|
4
|
+
def raises_argument_error(&block)
|
5
|
+
lambda {
|
6
|
+
block.call(described_class.new)
|
7
|
+
}.should raise_error(ArgumentError)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "raises an ArgumentError immediately when instances is empty" do
|
11
|
+
raises_argument_error do |arguments|
|
12
|
+
arguments.instances = []
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "raises an ArgumentError immediately when instances is something totally silly" do
|
17
|
+
raises_argument_error do |arguments|
|
18
|
+
arguments.instances = 42
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "raises an ArgumentError immediately when instances contains something totally silly" do
|
23
|
+
raises_argument_error do |arguments|
|
24
|
+
arguments.instances = [nil]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/spec/deploy_spec.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Serverside::Adapter::Deploy do
|
4
|
+
it_should_behave_like "it installs engineyard-serverside"
|
5
|
+
|
6
|
+
it_should_behave_like "it accepts app"
|
7
|
+
it_should_behave_like "it accepts framework_env"
|
8
|
+
it_should_behave_like "it accepts instances"
|
9
|
+
it_should_behave_like "it accepts migrate"
|
10
|
+
it_should_behave_like "it accepts ref"
|
11
|
+
it_should_behave_like "it accepts repo"
|
12
|
+
it_should_behave_like "it accepts stack"
|
13
|
+
it_should_behave_like "it accepts verbose"
|
14
|
+
|
15
|
+
it_should_require :app
|
16
|
+
it_should_require :instances
|
17
|
+
it_should_require :framework_env
|
18
|
+
it_should_require :ref
|
19
|
+
it_should_require :repo
|
20
|
+
it_should_require :stack
|
21
|
+
|
22
|
+
it_should_behave_like "it treats config as optional"
|
23
|
+
it_should_behave_like "it treats migrate as optional"
|
24
|
+
|
25
|
+
context "with valid arguments" do
|
26
|
+
let(:command) do
|
27
|
+
adapter = described_class.new do |arguments|
|
28
|
+
arguments.app = "rackapp"
|
29
|
+
arguments.framework_env = 'production'
|
30
|
+
arguments.config = {'a' => 1}
|
31
|
+
arguments.instances = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
|
32
|
+
arguments.migrate = 'rake db:migrate'
|
33
|
+
arguments.ref = 'master'
|
34
|
+
arguments.repo = 'git@github.com:engineyard/engineyard-serverside.git'
|
35
|
+
arguments.stack = "nginx_unicorn"
|
36
|
+
end
|
37
|
+
last_command(adapter)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "puts the config in the command line as json" do
|
41
|
+
command.should =~ /--config '#{Regexp.quote '{"a":1}'}'/
|
42
|
+
end
|
43
|
+
|
44
|
+
it "invokes exactly the right command" do
|
45
|
+
command.should == "engineyard-serverside _#{EY::Serverside::Adapter::VERSION}_ deploy --app rackapp --config '{\"a\":1}' --framework-env production --instance-names localhost:chewie --instance-roles localhost:han,solo --instances localhost --migrate 'rake db:migrate' --ref master --repo git@github.com:engineyard/engineyard-serverside.git --stack nginx_unicorn"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Serverside::Adapter::DisableMaintenancePage do
|
4
|
+
it_should_behave_like "it installs engineyard-serverside"
|
5
|
+
|
6
|
+
it_should_behave_like "it accepts app"
|
7
|
+
it_should_behave_like "it accepts instances"
|
8
|
+
it_should_behave_like "it accepts verbose"
|
9
|
+
|
10
|
+
it_should_require :app
|
11
|
+
it_should_require :instances
|
12
|
+
|
13
|
+
context "with valid arguments" do
|
14
|
+
let(:command) do
|
15
|
+
adapter = described_class.new do |arguments|
|
16
|
+
arguments.app = "rackapp"
|
17
|
+
arguments.instances = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
|
18
|
+
end
|
19
|
+
last_command(adapter)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "invokes exactly the right command" do
|
23
|
+
command.should == "engineyard-serverside _#{EY::Serverside::Adapter::VERSION}_ deploy disable_maintenance_page --app rackapp --instance-names localhost:chewie --instance-roles localhost:han,solo --instances localhost"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Serverside::Adapter::EnableMaintenancePage do
|
4
|
+
it_should_behave_like "it installs engineyard-serverside"
|
5
|
+
|
6
|
+
it_should_behave_like "it accepts app"
|
7
|
+
it_should_behave_like "it accepts instances"
|
8
|
+
it_should_behave_like "it accepts verbose"
|
9
|
+
|
10
|
+
it_should_require :app
|
11
|
+
it_should_require :instances
|
12
|
+
|
13
|
+
context "with valid arguments" do
|
14
|
+
|
15
|
+
let(:command) do
|
16
|
+
adapter = described_class.new do |arguments|
|
17
|
+
arguments.app = "rackapp"
|
18
|
+
arguments.instances = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
|
19
|
+
end
|
20
|
+
last_command(adapter)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "invokes exactly the right command" do
|
24
|
+
command.should == "engineyard-serverside _#{EY::Serverside::Adapter::VERSION}_ deploy enable_maintenance_page --app rackapp --instance-names localhost:chewie --instance-roles localhost:han,solo --instances localhost"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Serverside::Adapter::Integrate do
|
4
|
+
it_should_behave_like "it installs engineyard-serverside"
|
5
|
+
|
6
|
+
it_should_behave_like "it accepts app"
|
7
|
+
it_should_behave_like "it accepts framework_env"
|
8
|
+
it_should_behave_like "it accepts instances"
|
9
|
+
it_should_behave_like "it accepts stack"
|
10
|
+
it_should_behave_like "it accepts verbose"
|
11
|
+
|
12
|
+
it_should_require :app
|
13
|
+
it_should_require :stack
|
14
|
+
it_should_require :instances
|
15
|
+
it_should_require :framework_env
|
16
|
+
|
17
|
+
context "with valid arguments" do
|
18
|
+
let(:command) do
|
19
|
+
adapter = described_class.new do |arguments|
|
20
|
+
arguments.app = "rackapp"
|
21
|
+
arguments.instances = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
|
22
|
+
arguments.stack = "nginx_unicorn"
|
23
|
+
arguments.framework_env = "production"
|
24
|
+
end
|
25
|
+
last_command(adapter)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "invokes exactly the right command" do
|
29
|
+
command.should == "engineyard-serverside _#{EY::Serverside::Adapter::VERSION}_ integrate --app rackapp --framework-env production --instance-names localhost:chewie --instance-roles localhost:han,solo --instances localhost --stack nginx_unicorn"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Serverside::Adapter::Rollback do
|
4
|
+
it_should_behave_like "it installs engineyard-serverside"
|
5
|
+
|
6
|
+
it_should_behave_like "it accepts app"
|
7
|
+
it_should_behave_like "it accepts instances"
|
8
|
+
it_should_behave_like "it accepts stack"
|
9
|
+
it_should_behave_like "it accepts verbose"
|
10
|
+
|
11
|
+
it_should_require :app
|
12
|
+
it_should_require :stack
|
13
|
+
it_should_require :instances
|
14
|
+
|
15
|
+
context "with valid arguments" do
|
16
|
+
let(:command) do
|
17
|
+
adapter = described_class.new do |arguments|
|
18
|
+
arguments.app = "rackapp"
|
19
|
+
arguments.instances = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
|
20
|
+
arguments.stack = "nginx_unicorn"
|
21
|
+
arguments.config = {'a' => 1}
|
22
|
+
end
|
23
|
+
last_command(adapter)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "puts the config in the command line as json" do
|
27
|
+
command.should =~ /--config '#{Regexp.quote '{"a":1}'}'/
|
28
|
+
end
|
29
|
+
|
30
|
+
it "invokes exactly the right command" do
|
31
|
+
command.should == "engineyard-serverside _#{EY::Serverside::Adapter::VERSION}_ deploy rollback --app rackapp --config '{\"a\":1}' --instance-names localhost:chewie --instance-roles localhost:han,solo --instances localhost --stack nginx_unicorn"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'engineyard-serverside-adapter'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
module ArgumentsHelpers
|
8
|
+
def valid_options
|
9
|
+
{
|
10
|
+
:app => 'rackapp',
|
11
|
+
:framework_env => 'production',
|
12
|
+
:instances => [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}],
|
13
|
+
:ref => 'master',
|
14
|
+
:repo => 'git@github.com:engineyard/engineyard-serverside.git',
|
15
|
+
:stack => 'nginx_unicorn',
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid_arguments() arguments_without() end # without nothing --> valid :)
|
20
|
+
|
21
|
+
def arguments_with(fields)
|
22
|
+
arguments = valid_arguments
|
23
|
+
fields.each do |field, value|
|
24
|
+
arguments.send("#{field}=", value)
|
25
|
+
end
|
26
|
+
arguments
|
27
|
+
end
|
28
|
+
|
29
|
+
def arguments_without(*fields)
|
30
|
+
arguments = EY::Serverside::Adapter::Arguments.new
|
31
|
+
valid_options.each do |field, value|
|
32
|
+
arguments.send("#{field}=", value) unless fields.include?(field)
|
33
|
+
end
|
34
|
+
arguments
|
35
|
+
end
|
36
|
+
|
37
|
+
def all_commands(adapter)
|
38
|
+
commands = []
|
39
|
+
adapter.call { |command| commands << command }
|
40
|
+
commands
|
41
|
+
end
|
42
|
+
|
43
|
+
def last_command(adapter)
|
44
|
+
all_commands(adapter).last
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module RequiredFieldHelpers
|
49
|
+
def it_should_require(field)
|
50
|
+
context "field #{field}" do
|
51
|
+
it "is just fine when #{field} is there" do
|
52
|
+
lambda { described_class.new(:arguments => valid_arguments) }.should_not raise_error
|
53
|
+
end
|
54
|
+
|
55
|
+
it "raises an error if #{field} is missing" do
|
56
|
+
lambda { described_class.new(:arguments => arguments_without(field)) }.should raise_error(ArgumentError)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
Spec::Runner.configure do |config|
|
63
|
+
config.include ArgumentsHelpers
|
64
|
+
config.extend RequiredFieldHelpers
|
65
|
+
|
66
|
+
shared_examples_for "it installs engineyard-serverside" do
|
67
|
+
it "checks for and installs engineyard-serverside before invoking it" do
|
68
|
+
adapter = described_class.new(:arguments => valid_arguments)
|
69
|
+
|
70
|
+
all_commands(adapter).size.should == 2
|
71
|
+
installation_command = all_commands(adapter).first
|
72
|
+
|
73
|
+
# of course, the only way to be sure is to actually run it, but
|
74
|
+
# this gives us regression-proofing
|
75
|
+
version = EY::Serverside::Adapter::ENGINEYARD_SERVERSIDE_VERSION
|
76
|
+
escaped_version = version.gsub(/\./, '\\.')
|
77
|
+
installation_command.should == "(gem list engineyard-serverside | grep 'engineyard-serverside ' | egrep -q '#{escaped_version}[,)]') || (sudo sh -c 'cd `mktemp -d` && gem install engineyard-serverside --no-rdoc --no-ri -v #{version}')"
|
78
|
+
|
79
|
+
|
80
|
+
installation_command.should =~ /gem list engineyard-serverside/
|
81
|
+
installation_command.should =~ /egrep -q /
|
82
|
+
installation_command.should =~ /gem install engineyard-serverside.*-v #{Regexp.quote EY::Serverside::Adapter::VERSION}/
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
shared_examples_for "it accepts verbose" do
|
87
|
+
context "the --verbose arg" do
|
88
|
+
it "is present when you set verbose to true" do
|
89
|
+
adapter = described_class.new(:arguments => arguments_with(:verbose => true))
|
90
|
+
last_command(adapter).should =~ /--verbose/
|
91
|
+
end
|
92
|
+
|
93
|
+
it "is absent when you set verbose to false" do
|
94
|
+
adapter = described_class.new(:arguments => arguments_with(:verbose => false))
|
95
|
+
last_command(adapter).should_not =~ /--verbose/
|
96
|
+
end
|
97
|
+
|
98
|
+
it "is absent when you omit verbose" do
|
99
|
+
adapter = described_class.new(:arguments => valid_arguments)
|
100
|
+
last_command(adapter).should_not =~ /--verbose/
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
{
|
106
|
+
:app => '--app',
|
107
|
+
:stack => '--stack',
|
108
|
+
:framework_env => '--framework-env',
|
109
|
+
:ref => '--ref',
|
110
|
+
:repo => '--repo',
|
111
|
+
:migrate => '--migrate',
|
112
|
+
}.each do |arg, switch|
|
113
|
+
shared_examples_for "it accepts #{arg}" do
|
114
|
+
it "puts the #{switch} arg in the command line" do
|
115
|
+
adapter = described_class.new(:arguments => arguments_with(arg => 'word'))
|
116
|
+
last_command(adapter).should =~ /#{switch} word/
|
117
|
+
end
|
118
|
+
|
119
|
+
it "handles arguments that need to be escaped" do
|
120
|
+
adapter = described_class.new(:arguments => arguments_with(arg => 'two words'))
|
121
|
+
last_command(adapter).should =~ /#{switch} 'two words'/
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
shared_examples_for "it treats #{arg} as optional" do
|
126
|
+
it "omits #{switch} when you don't give it #{arg}" do
|
127
|
+
adapter = described_class.new(:arguments => arguments_without(arg))
|
128
|
+
last_command(adapter).should_not include(switch)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
shared_examples_for "it treats config as optional" do
|
135
|
+
it "omits --config when you don't give it config" do
|
136
|
+
adapter = described_class.new(:arguments => arguments_without(:config))
|
137
|
+
last_command(adapter).should_not include('--config')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
shared_examples_for "it accepts instances" do
|
142
|
+
context "given an unnamed instance" do
|
143
|
+
it "puts the instance in the command line" do
|
144
|
+
adapter = described_class.new(:arguments => arguments_with(
|
145
|
+
:instances => [{:hostname => 'localhost', :roles => %w[han solo], :name => nil}]
|
146
|
+
))
|
147
|
+
command = last_command(adapter)
|
148
|
+
command.should =~ /--instances localhost/
|
149
|
+
command.should =~ /--instance-roles localhost:han,solo/
|
150
|
+
command.should_not =~ /--instance-names/
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "given a named instance" do
|
155
|
+
it "puts the instance in the command line" do
|
156
|
+
adapter = described_class.new(:arguments => arguments_with(
|
157
|
+
:instances => [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
|
158
|
+
))
|
159
|
+
command = last_command(adapter)
|
160
|
+
command.should =~ /--instances localhost/
|
161
|
+
command.should =~ /--instance-roles localhost:han,solo/
|
162
|
+
command.should =~ /--instance-names localhost:chewie/
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "given multiple instances" do
|
167
|
+
it "puts the instance in the command line" do
|
168
|
+
adapter = described_class.new(:arguments => arguments_with({
|
169
|
+
:instances => [
|
170
|
+
{:hostname => 'localhost', :roles => %w[wookie], :name => 'chewie'},
|
171
|
+
{:hostname => 'crazy-ass-amazon-1243324321.domain', :roles => %w[bounty-hunter], :name => nil},
|
172
|
+
{:hostname => 'simpler.domain', :roles => %w[pilot scruffy-lookin-nerf-herder], :name => 'han'},
|
173
|
+
]
|
174
|
+
}))
|
175
|
+
command = last_command(adapter)
|
176
|
+
command.should =~ /--instances crazy-ass-amazon-1243324321.domain localhost simpler.domain/
|
177
|
+
command.should =~ /--instance-roles crazy-ass-amazon-1243324321.domain:bounty-hunter localhost:wookie simpler.domain:pilot,scruffy-lookin-nerf-herder/
|
178
|
+
command.should =~ /--instance-names localhost:chewie simpler.domain:han/
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: engineyard-serverside-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 961915976
|
5
|
+
prerelease: true
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 3
|
9
|
+
- 1
|
10
|
+
- pre
|
11
|
+
version: 1.3.1.pre
|
12
|
+
platform: ruby
|
13
|
+
authors: []
|
14
|
+
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-09-15 00:00:00 -07:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: escape
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 23
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
- 4
|
35
|
+
version: 0.0.4
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: json_pure
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
hash: 11
|
47
|
+
segments:
|
48
|
+
- 1
|
49
|
+
- 4
|
50
|
+
- 6
|
51
|
+
version: 1.4.6
|
52
|
+
type: :runtime
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: bundler
|
56
|
+
prerelease: false
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 23
|
63
|
+
segments:
|
64
|
+
- 1
|
65
|
+
- 0
|
66
|
+
- 0
|
67
|
+
version: 1.0.0
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id003
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 27
|
79
|
+
segments:
|
80
|
+
- 1
|
81
|
+
- 3
|
82
|
+
- 0
|
83
|
+
version: 1.3.0
|
84
|
+
type: :development
|
85
|
+
version_requirements: *id004
|
86
|
+
description: A separate adapter for speaking the CLI language of the engineyard-serverside gem.
|
87
|
+
email: []
|
88
|
+
|
89
|
+
executables: []
|
90
|
+
|
91
|
+
extensions: []
|
92
|
+
|
93
|
+
extra_rdoc_files: []
|
94
|
+
|
95
|
+
files:
|
96
|
+
- .gitignore
|
97
|
+
- Gemfile
|
98
|
+
- Rakefile
|
99
|
+
- engineyard-serverside-adapter.gemspec
|
100
|
+
- lib/engineyard-serverside-adapter.rb
|
101
|
+
- lib/engineyard-serverside-adapter/action.rb
|
102
|
+
- lib/engineyard-serverside-adapter/arguments.rb
|
103
|
+
- lib/engineyard-serverside-adapter/command.rb
|
104
|
+
- lib/engineyard-serverside-adapter/deploy.rb
|
105
|
+
- lib/engineyard-serverside-adapter/disable_maintenance_page.rb
|
106
|
+
- lib/engineyard-serverside-adapter/enable_maintenance_page.rb
|
107
|
+
- lib/engineyard-serverside-adapter/integrate.rb
|
108
|
+
- lib/engineyard-serverside-adapter/rollback.rb
|
109
|
+
- lib/engineyard-serverside-adapter/version.rb
|
110
|
+
- spec/adapter_spec.rb
|
111
|
+
- spec/arguments_spec.rb
|
112
|
+
- spec/deploy_spec.rb
|
113
|
+
- spec/disable_maintenance_page_spec.rb
|
114
|
+
- spec/enable_maintenance_page_spec.rb
|
115
|
+
- spec/integrate_spec.rb
|
116
|
+
- spec/rollback_spec.rb
|
117
|
+
- spec/spec.opts
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
has_rdoc: true
|
120
|
+
homepage: http://github.com/engineyard/engineyard-serverside-adapter
|
121
|
+
licenses: []
|
122
|
+
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
hash: 3
|
134
|
+
segments:
|
135
|
+
- 0
|
136
|
+
version: "0"
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
hash: 23
|
143
|
+
segments:
|
144
|
+
- 1
|
145
|
+
- 3
|
146
|
+
- 6
|
147
|
+
version: 1.3.6
|
148
|
+
requirements: []
|
149
|
+
|
150
|
+
rubyforge_project: engineyard-serverside-adapter
|
151
|
+
rubygems_version: 1.3.7
|
152
|
+
signing_key:
|
153
|
+
specification_version: 3
|
154
|
+
summary: Adapter for speaking to engineyard-serverside
|
155
|
+
test_files: []
|
156
|
+
|