sprinkle 0.1.4
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/CREDITS +14 -0
- data/History.txt +4 -0
- data/MIT-LICENSE +20 -0
- data/Manifest.txt +63 -0
- data/README.rdoc +218 -0
- data/Rakefile +4 -0
- data/TODO +56 -0
- data/bin/sprinkle +79 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +17 -0
- data/examples/merb/deploy.rb +5 -0
- data/examples/rails/README +15 -0
- data/examples/rails/deploy.rb +2 -0
- data/examples/rails/packages/database.rb +9 -0
- data/examples/rails/packages/essential.rb +6 -0
- data/examples/rails/packages/rails.rb +28 -0
- data/examples/rails/packages/search.rb +11 -0
- data/examples/rails/packages/server.rb +28 -0
- data/examples/rails/rails.rb +71 -0
- data/examples/sprinkle/sprinkle.rb +38 -0
- data/lib/sprinkle/actors/capistrano.rb +80 -0
- data/lib/sprinkle/actors/vlad.rb +30 -0
- data/lib/sprinkle/deployment.rb +33 -0
- data/lib/sprinkle/extensions/arbitrary_options.rb +10 -0
- data/lib/sprinkle/extensions/array.rb +7 -0
- data/lib/sprinkle/extensions/blank_slate.rb +5 -0
- data/lib/sprinkle/extensions/dsl_accessor.rb +15 -0
- data/lib/sprinkle/extensions/string.rb +10 -0
- data/lib/sprinkle/extensions/symbol.rb +7 -0
- data/lib/sprinkle/installers/apt.rb +20 -0
- data/lib/sprinkle/installers/gem.rb +33 -0
- data/lib/sprinkle/installers/installer.rb +85 -0
- data/lib/sprinkle/installers/rake.rb +17 -0
- data/lib/sprinkle/installers/rpm.rb +20 -0
- data/lib/sprinkle/installers/source.rb +120 -0
- data/lib/sprinkle/package.rb +94 -0
- data/lib/sprinkle/policy.rb +85 -0
- data/lib/sprinkle/script.rb +13 -0
- data/lib/sprinkle/sequence.rb +21 -0
- data/lib/sprinkle/version.rb +9 -0
- data/lib/sprinkle.rb +26 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/sprinkle/actors/capistrano_spec.rb +150 -0
- data/spec/sprinkle/deployment_spec.rb +80 -0
- data/spec/sprinkle/extensions/array_spec.rb +19 -0
- data/spec/sprinkle/extensions/string_spec.rb +21 -0
- data/spec/sprinkle/installers/apt_spec.rb +53 -0
- data/spec/sprinkle/installers/gem_spec.rb +75 -0
- data/spec/sprinkle/installers/installer_spec.rb +125 -0
- data/spec/sprinkle/installers/rpm_spec.rb +50 -0
- data/spec/sprinkle/installers/source_spec.rb +315 -0
- data/spec/sprinkle/package_spec.rb +247 -0
- data/spec/sprinkle/policy_spec.rb +126 -0
- data/spec/sprinkle/script_spec.rb +51 -0
- data/spec/sprinkle/sequence_spec.rb +44 -0
- data/spec/sprinkle/sprinkle_spec.rb +25 -0
- data/sprinkle.gemspec +43 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- metadata +157 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
module Package
|
3
|
+
PACKAGES = {}
|
4
|
+
|
5
|
+
def package(name, metadata = {}, &block)
|
6
|
+
package = Package.new(name, metadata, &block)
|
7
|
+
PACKAGES[name] = package
|
8
|
+
|
9
|
+
if package.provides
|
10
|
+
(PACKAGES[package.provides] ||= []) << package
|
11
|
+
end
|
12
|
+
|
13
|
+
package
|
14
|
+
end
|
15
|
+
|
16
|
+
class Package
|
17
|
+
include ArbitraryOptions
|
18
|
+
attr_accessor :name, :provides, :installer, :dependencies, :recommends
|
19
|
+
|
20
|
+
def initialize(name, metadata = {}, &block)
|
21
|
+
raise 'No package name supplied' unless name
|
22
|
+
|
23
|
+
@name = name
|
24
|
+
@provides = metadata[:provides]
|
25
|
+
@dependencies = []
|
26
|
+
@recommends = []
|
27
|
+
self.instance_eval &block
|
28
|
+
end
|
29
|
+
|
30
|
+
def apt(*names)
|
31
|
+
@installer = Sprinkle::Installers::Apt.new(self, *names)
|
32
|
+
end
|
33
|
+
|
34
|
+
def rpm(*names)
|
35
|
+
@installer = Sprinkle::Installers::Rpm.new(self, *names)
|
36
|
+
end
|
37
|
+
|
38
|
+
def gem(name, options = {}, &block)
|
39
|
+
@recommends << :rubygems
|
40
|
+
@installer = Sprinkle::Installers::Gem.new(self, name, options, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def source(source, options = {}, &block)
|
44
|
+
@recommends << :build_essential # Ubuntu/Debian
|
45
|
+
@installer = Sprinkle::Installers::Source.new(self, source, options, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def process(deployment, roles)
|
49
|
+
return if meta_package?
|
50
|
+
|
51
|
+
@installer.defaults(deployment)
|
52
|
+
@installer.process(roles)
|
53
|
+
end
|
54
|
+
|
55
|
+
def requires(*packages)
|
56
|
+
@dependencies << packages
|
57
|
+
@dependencies.flatten!
|
58
|
+
end
|
59
|
+
|
60
|
+
def recommends(*packages)
|
61
|
+
@recommends << packages
|
62
|
+
@recommends.flatten!
|
63
|
+
end
|
64
|
+
|
65
|
+
def tree(depth = 1, &block)
|
66
|
+
packages = []
|
67
|
+
|
68
|
+
@recommends.each do |dep|
|
69
|
+
package = PACKAGES[dep]
|
70
|
+
next unless package # skip missing recommended packages as they can be optional
|
71
|
+
block.call(self, package, depth) if block
|
72
|
+
packages << package.tree(depth + 1, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
@dependencies.each do |dep|
|
76
|
+
package = PACKAGES[dep]
|
77
|
+
raise "Package definition not found for key: #{dep}" unless package
|
78
|
+
block.call(self, package, depth) if block
|
79
|
+
packages << package.tree(depth + 1, &block)
|
80
|
+
end
|
81
|
+
|
82
|
+
packages << self
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s; @name; end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def meta_package?
|
90
|
+
@installer == nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'highline/import'
|
2
|
+
|
3
|
+
module Sprinkle
|
4
|
+
module Policy
|
5
|
+
POLICIES = []
|
6
|
+
|
7
|
+
def policy(name, options = {}, &block)
|
8
|
+
p = Policy.new(name, options, &block)
|
9
|
+
POLICIES << p
|
10
|
+
p
|
11
|
+
end
|
12
|
+
|
13
|
+
class Policy
|
14
|
+
attr_reader :name, :packages
|
15
|
+
|
16
|
+
def initialize(name, metadata = {}, &block)
|
17
|
+
raise 'No name provided' unless name
|
18
|
+
raise 'No roles provided' unless metadata[:roles]
|
19
|
+
|
20
|
+
@name = name
|
21
|
+
@roles = metadata[:roles]
|
22
|
+
@packages = []
|
23
|
+
self.instance_eval(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def requires(package, options = {})
|
27
|
+
@packages << package
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s; name; end
|
31
|
+
|
32
|
+
def process(deployment)
|
33
|
+
all = []
|
34
|
+
|
35
|
+
cloud_info "--> Cloud hierarchy for policy #{@name}"
|
36
|
+
|
37
|
+
@packages.each do |p|
|
38
|
+
cloud_info "\nPolicy #{@name} requires package #{p}"
|
39
|
+
|
40
|
+
package = Sprinkle::Package::PACKAGES[p]
|
41
|
+
raise "Package definition not found for key: #{p}" unless package
|
42
|
+
package = select_package(p, package) if package.is_a? Array # handle virtual package selection
|
43
|
+
|
44
|
+
tree = package.tree do |parent, child, depth|
|
45
|
+
indent = "\t" * depth; cloud_info "#{indent}Package #{parent.name} requires #{child.name}"
|
46
|
+
end
|
47
|
+
|
48
|
+
all << tree
|
49
|
+
end
|
50
|
+
|
51
|
+
normalize(all) do |package|
|
52
|
+
package.process(deployment, @roles)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def cloud_info(message)
|
59
|
+
logger.info(message) if Sprinkle::OPTIONS[:cloud] or logger.debug?
|
60
|
+
end
|
61
|
+
|
62
|
+
def select_package(name, packages)
|
63
|
+
if packages.size <= 1
|
64
|
+
package = packages.first
|
65
|
+
else
|
66
|
+
package = choose do |menu|
|
67
|
+
menu.prompt = "Multiple choices exist for virtual package #{name}"
|
68
|
+
menu.choices *packages.collect(&:to_s)
|
69
|
+
end
|
70
|
+
package = Sprinkle::Package::PACKAGES[package]
|
71
|
+
end
|
72
|
+
|
73
|
+
cloud_info "Selecting #{package.to_s} for virtual package #{name}"
|
74
|
+
|
75
|
+
package
|
76
|
+
end
|
77
|
+
|
78
|
+
def normalize(all, &block)
|
79
|
+
all = all.flatten.uniq
|
80
|
+
cloud_info "\n--> Normalized installation order for all packages: #{all.collect(&:name).join(', ')}"
|
81
|
+
all.each &block
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
class Sequence
|
3
|
+
attr_accessor :stages
|
4
|
+
|
5
|
+
def initialize(&block)
|
6
|
+
self.instance_eval &block if block
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(sym, *args, &block)
|
10
|
+
@stages ||= ActiveSupport::OrderedHash.new
|
11
|
+
@stages[sym] = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(&block)
|
15
|
+
@stages.each do |section, commands|
|
16
|
+
block.call section, commands.call
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/sprinkle.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
|
4
|
+
# Use active supports auto load mechanism
|
5
|
+
Dependencies.load_paths << File.dirname(__FILE__)
|
6
|
+
|
7
|
+
# Configure active support to log auto-loading of dependencies
|
8
|
+
#Dependencies::RAILS_DEFAULT_LOGGER = Logger.new($stdout)
|
9
|
+
#Dependencies.log_activity = true
|
10
|
+
|
11
|
+
# Load up extensions to existing classes
|
12
|
+
Dir[File.dirname(__FILE__) + '/sprinkle/extensions/*.rb'].each { |e| require e }
|
13
|
+
|
14
|
+
# Configuration options
|
15
|
+
module Sprinkle
|
16
|
+
OPTIONS = { :testing => false, :verbose => false }
|
17
|
+
end
|
18
|
+
|
19
|
+
# Define a logging target and understand packages, policies and deployment DSL
|
20
|
+
class Object
|
21
|
+
include Sprinkle::Package, Sprinkle::Policy, Sprinkle::Deployment
|
22
|
+
|
23
|
+
def logger
|
24
|
+
@@__log__ ||= ActiveSupport::BufferedLogger.new($stdout, ActiveSupport::BufferedLogger::Severity::INFO)
|
25
|
+
end
|
26
|
+
end
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
gem 'rspec'
|
6
|
+
require 'spec'
|
7
|
+
end
|
8
|
+
|
9
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
10
|
+
require 'sprinkle'
|
11
|
+
|
12
|
+
module Kernel
|
13
|
+
def logger
|
14
|
+
@@__log_file__ ||= StringIO.new
|
15
|
+
@@__log__ = ActiveSupport::BufferedLogger.new @@__log_file__
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Sprinkle::Actors::Capistrano do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@recipes = 'deploy'
|
7
|
+
@cap = ::Capistrano::Configuration.new
|
8
|
+
::Capistrano::Configuration.stub!(:new).and_return(@cap)
|
9
|
+
@cap.stub!(:load).and_return
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_cap(&block)
|
13
|
+
Sprinkle::Actors::Capistrano.new &block
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'when created' do
|
17
|
+
|
18
|
+
it 'should create a new capistrano object' do
|
19
|
+
::Capistrano::Configuration.should_receive(:new).and_return(@cap)
|
20
|
+
create_cap
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'when verbose' do
|
24
|
+
|
25
|
+
before do
|
26
|
+
Sprinkle::OPTIONS[:verbose] = true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should set verbose logging on the capistrano object' do
|
30
|
+
@cap = create_cap
|
31
|
+
@cap.config.logger.level.should == ::Capistrano::Logger::INFO
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'when not verbose' do
|
37
|
+
|
38
|
+
before do
|
39
|
+
Sprinkle::OPTIONS[:verbose] = false
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should set quiet logging on the capistrano object' do
|
43
|
+
@cap = create_cap
|
44
|
+
@cap.config.logger.level.should == ::Capistrano::Logger::IMPORTANT
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'with a block' do
|
50
|
+
|
51
|
+
before do
|
52
|
+
@actor = create_cap do
|
53
|
+
recipes 'cool gear' # default is deploy
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should evaluate the block against the actor instance' do
|
58
|
+
@actor.loaded_recipes.should include('cool gear')
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'without a block' do
|
64
|
+
|
65
|
+
it 'should automatically load the default capistrano configuration' do
|
66
|
+
@cap.should_receive(:load).with('deploy').and_return
|
67
|
+
end
|
68
|
+
|
69
|
+
after do
|
70
|
+
@actor = create_cap
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'recipes' do
|
78
|
+
|
79
|
+
it 'should add the recipe location to an internal store' do
|
80
|
+
@cap = create_cap do
|
81
|
+
recipes 'deploy'
|
82
|
+
end
|
83
|
+
@cap.loaded_recipes.should == [ @recipes ]
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should load the given recipe' do
|
87
|
+
@cap.should_receive(:load).with(@recipes).and_return
|
88
|
+
create_cap
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'processing commands' do
|
94
|
+
|
95
|
+
before do
|
96
|
+
@commands = %w( op1 op2 )
|
97
|
+
@roles = %w( app )
|
98
|
+
@name = 'name'
|
99
|
+
|
100
|
+
@cap = create_cap do; recipes 'deploy'; end
|
101
|
+
@cap.stub!(:run).and_return
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should dynamically create a capistrano task containing the commands' do
|
105
|
+
@cap.config.should_receive(:task).and_return
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should invoke capistrano task after creation' do
|
109
|
+
@cap.should_receive(:run).with(@name).and_return
|
110
|
+
end
|
111
|
+
|
112
|
+
after do
|
113
|
+
@cap.process @name, @commands, @roles
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'generated task' do
|
119
|
+
|
120
|
+
before do
|
121
|
+
@commands = %w( op1 op2 )
|
122
|
+
@roles = %w( app )
|
123
|
+
@name = 'name'
|
124
|
+
|
125
|
+
@cap = create_cap do; recipes 'deploy'; end
|
126
|
+
@cap.config.stub!(:fetch).and_return(:sudo)
|
127
|
+
@cap.config.stub!(:invoke_command).and_return
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should use sudo to invoke commands when so configured' do
|
131
|
+
@cap.config.should_receive(:fetch).with(:run_method, :sudo).and_return(:sudo)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should run the supplied commands' do
|
135
|
+
@cap.config.should_receive(:invoke_command).with('op1', :via => :sudo).ordered.and_return
|
136
|
+
@cap.config.should_receive(:invoke_command).with('op2', :via => :sudo).ordered.and_return
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should be applicable for the supplied roles' do
|
140
|
+
@cap.stub!(:run).and_return
|
141
|
+
@cap.config.should_receive(:task).with(:install_name, :roles => @roles).and_return
|
142
|
+
end
|
143
|
+
|
144
|
+
after do
|
145
|
+
@cap.process @name, @commands, @roles
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Sprinkle::Deployment do
|
4
|
+
include Sprinkle::Deployment
|
5
|
+
|
6
|
+
def create_deployment(&block)
|
7
|
+
deployment do
|
8
|
+
delivery :capistrano, &block
|
9
|
+
|
10
|
+
source do
|
11
|
+
prefix '/usr/local'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'when created' do
|
17
|
+
|
18
|
+
it 'should be invalid without a block descriptor' do
|
19
|
+
lambda { deployment }.should raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should be invalid without a delivery method' do
|
23
|
+
lambda { @deployment = deployment do; end }.should raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should optionally accept installer defaults' do
|
27
|
+
@deployment = create_deployment
|
28
|
+
@deployment.should respond_to(:source)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should provide installer defaults as a proc when requested' do
|
32
|
+
@deployment = create_deployment
|
33
|
+
@deployment.defaults[:source].class.should == Proc
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'delivery specification' do
|
39
|
+
|
40
|
+
before do
|
41
|
+
@actor = mock(Sprinkle::Actors::Capistrano)
|
42
|
+
Sprinkle::Actors::Capistrano.stub!(:new).and_return(@actor)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should automatically instantiate the delivery type' do
|
46
|
+
@deployment = create_deployment
|
47
|
+
@deployment.style.should == @actor
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should optionally accept a block to pass to the actor' do
|
51
|
+
lambda { @deployment = create_deployment }.should_not raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'with a block' do
|
55
|
+
|
56
|
+
it 'should pass the block to the actor for configuration' do
|
57
|
+
@deployment = create_deployment do; recipes 'deploy'; end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'when processing policies' do
|
64
|
+
|
65
|
+
before do
|
66
|
+
@policy = mock(Policy, :process => true)
|
67
|
+
POLICIES = [ @policy ]
|
68
|
+
@deployment = create_deployment
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should apply all policies, passing itself as the deployment context' do
|
72
|
+
@policy.should_receive(:process).with(@deployment).and_return
|
73
|
+
end
|
74
|
+
|
75
|
+
after do
|
76
|
+
@deployment.process
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Array, 'task name conversions' do
|
4
|
+
|
5
|
+
it 'should be able to deliver a task name' do
|
6
|
+
['build_essential'].to_task_name.should == 'build_essential'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should join multiple elements together with a _ char' do
|
10
|
+
['gdb', 'gcc', 'g++'].to_task_name.should == 'gdb_gcc_g++'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should use the task name of the underlying array element' do
|
14
|
+
string = 'build-essential'
|
15
|
+
string.should_receive(:to_task_name).and_return('build_essential')
|
16
|
+
[string].to_task_name.should == 'build_essential'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe String, 'task name conversions' do
|
4
|
+
|
5
|
+
it 'should be able to deliver a task name' do
|
6
|
+
'build_essential'.to_task_name.should == 'build_essential'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should convert all - chars to _ in the task name' do
|
10
|
+
'build-essential'.to_task_name.should == 'build_essential'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should convert multiple - chars to _ chars in the task name' do
|
14
|
+
'build--essential'.to_task_name.should == 'build__essential'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should lowercase the task name' do
|
18
|
+
'BUILD-ESSENTIAL'.to_task_name.should == 'build_essential'
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Sprinkle::Installers::Apt do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@package = mock(Sprinkle::Package, :name => 'package')
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_apt(debs, &block)
|
10
|
+
Sprinkle::Installers::Apt.new(@package, debs, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'when created' do
|
14
|
+
|
15
|
+
it 'should accept a single package to install' do
|
16
|
+
@installer = create_apt 'ruby'
|
17
|
+
@installer.packages.should == [ 'ruby' ]
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should accept an array of packages to install' do
|
21
|
+
@installer = create_apt %w( gcc gdb g++ )
|
22
|
+
@installer.packages.should == ['gcc', 'gdb', 'g++']
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'during installation' do
|
28
|
+
|
29
|
+
before do
|
30
|
+
@installer = create_apt 'ruby' do
|
31
|
+
pre :install, 'op1'
|
32
|
+
post :install, 'op2'
|
33
|
+
end
|
34
|
+
@install_commands = @installer.send :install_commands
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should invoke the apt installer for all specified packages' do
|
38
|
+
@install_commands.should =~ /apt-get -qyu install ruby/
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should specify a non interactive mode to the apt installer' do
|
42
|
+
@install_commands.should =~ /DEBIAN_FRONTEND=noninteractive/
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should automatically insert pre/post commands for the specified package' do
|
46
|
+
@installer.send(:install_sequence).should == [ 'op1', %(DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive apt-get -qyu install ruby), 'op2' ]
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should install a specific version if defined'
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|