server-blender 0.0.8
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/.braids +8 -0
- data/.document +6 -0
- data/.gitignore +27 -0
- data/LICENSE +20 -0
- data/PLAN +13 -0
- data/README.markdown +65 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/blender +21 -0
- data/files/bootstrap.sh +240 -0
- data/lib/blender/cli/init.rb +44 -0
- data/lib/blender/cli/mix.rb +71 -0
- data/lib/blender/cli/start.rb +82 -0
- data/lib/blender.rb +5 -0
- data/server-blender.gemspec +87 -0
- data/spec/server-blender_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- data/vendor/server-blender-manifests/.gitignore +26 -0
- data/vendor/server-blender-manifests/LICENSE +20 -0
- data/vendor/server-blender-manifests/README.markdown +23 -0
- data/vendor/server-blender-manifests/Rakefile +40 -0
- data/vendor/server-blender-manifests/VERSION +1 -0
- data/vendor/server-blender-manifests/lib/blender/manifest/init.rb +23 -0
- data/vendor/server-blender-manifests/lib/blender/manifest/mixer.rb +35 -0
- data/vendor/server-blender-manifests/lib/blender/manifest/nodes.rb +94 -0
- data/vendor/server-blender-manifests/lib/blender/manifest/roles.rb +40 -0
- data/vendor/server-blender-manifests/lib/blender/manifest/root.rb +38 -0
- data/vendor/server-blender-manifests/server-blender-manifest.gemspec +58 -0
- data/vendor/server-blender-manifests/spec/spec.opts +1 -0
- data/vendor/server-blender-manifests/spec/spec_helper.rb +9 -0
- metadata +127 -0
data/.braids
ADDED
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
## MISC
|
2
|
+
pkg
|
3
|
+
tags
|
4
|
+
.yardoc
|
5
|
+
|
6
|
+
## MAC OS
|
7
|
+
.DS_Store
|
8
|
+
|
9
|
+
## TEXTMATE
|
10
|
+
*.tmproj
|
11
|
+
tmtags
|
12
|
+
|
13
|
+
## EMACS
|
14
|
+
*~
|
15
|
+
\#*
|
16
|
+
.\#*
|
17
|
+
|
18
|
+
## VIM
|
19
|
+
*.swp
|
20
|
+
|
21
|
+
## PROJECT::GENERAL
|
22
|
+
coverage
|
23
|
+
rdoc
|
24
|
+
pkg
|
25
|
+
|
26
|
+
## PROJECT::SPECIFIC
|
27
|
+
doc
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Vitaly Kushner
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/PLAN
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Server Blender
|
2
|
+
|
3
|
+
IMPORTANT: this is pre-alpha. interface is not near being stable. I'm still
|
4
|
+
working on making it not-a-hack :)
|
5
|
+
|
6
|
+
(Note to self: write the tests already you lazy bastard! ;)
|
7
|
+
|
8
|
+
* Home: [http://astrails.com/opensource/server-blender](http://astrails.com/opensource/server-blender)
|
9
|
+
* Code: [http://github.com/astrails/server-blender](http://github.com/astrails/server-blender)
|
10
|
+
* Blog: [http://blog.astrails.com/server-blender](http://blog.astrails.com/server-blender)
|
11
|
+
|
12
|
+
## Introduction
|
13
|
+
|
14
|
+
Boostrap and manage servers with shadow\_puppet
|
15
|
+
|
16
|
+
Blender tries to be a fairly minimal wrapper around [shadow\_puppet](http://github.com/railsmachine/shadow\_puppet)
|
17
|
+
|
18
|
+
shadow\_puppet is a Ruby interface to [Puppet](http://reductivelabs.com/products/puppet/) manifests.
|
19
|
+
|
20
|
+
During 'mixing' blender will transfer ALL files in the source directory to the
|
21
|
+
remote server and then execute the designated 'recipe' with shadow\_puppet.
|
22
|
+
|
23
|
+
## Quick Start
|
24
|
+
|
25
|
+
The intended usage workflow is as follows:
|
26
|
+
|
27
|
+
* (optional) blender start - to start a new server instance (currently only EC2 is supported)
|
28
|
+
* blender init root@HOSTNAME - install minimal system required to run blender recipes
|
29
|
+
* blender mix [-r RECIPE] [DIR] root@HOSTNAME
|
30
|
+
|
31
|
+
Note: root access through ssh is required for blender to work. There are no
|
32
|
+
current plans to support sudo or some other method of privilege elevation (but I will consider it if there is a popular demand. I'm definitely will accept patched for such support ;)
|
33
|
+
|
34
|
+
## Examples
|
35
|
+
|
36
|
+
initialize blender
|
37
|
+
|
38
|
+
$ blender init root@foobar.com
|
39
|
+
|
40
|
+
mix default recipe (default.rb) from directory my\_recipes
|
41
|
+
|
42
|
+
$ blender mix my_recipes root@foobar.com
|
43
|
+
|
44
|
+
mix recipe extra.rb from directory my\_recipes
|
45
|
+
|
46
|
+
$ blender mix my_recipes -r extra root@foobar.com # will run my_recipes/extra.rb
|
47
|
+
|
48
|
+
mix recipe extra.rb from the current directory
|
49
|
+
|
50
|
+
$ blender mix -r extra root@foobar.com # will run ./extra.rb
|
51
|
+
|
52
|
+
|
53
|
+
## Note on Patches/Pull Requests
|
54
|
+
|
55
|
+
* Fork the project.
|
56
|
+
* Make your feature addition or bug fix.
|
57
|
+
* Add tests for it. This is important so I don't break it in a
|
58
|
+
future version unintentionally.
|
59
|
+
* Commit, do not mess with rakefile, version, or history.
|
60
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
61
|
+
* Send me a pull request. Bonus points for topic branches.
|
62
|
+
|
63
|
+
## Copyright
|
64
|
+
|
65
|
+
Copyright (c) 2009 Vitaly Kushner. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "server-blender"
|
8
|
+
gem.summary = %Q{Server provisioning and configuration management tool}
|
9
|
+
gem.description = <<-DESC
|
10
|
+
Boostrap and manage servers with shadow\_puppet
|
11
|
+
|
12
|
+
Server Blender tries to be a fairly minimal wrapper around shadow\_puppet
|
13
|
+
http://github.com/railsmachine/shadow\_puppet
|
14
|
+
|
15
|
+
shadow\_puppet is a Ruby interface to Puppet's manifests.
|
16
|
+
http://reductivelabs.com/products/puppet/
|
17
|
+
DESC
|
18
|
+
gem.email = "vitaly@astrails.com"
|
19
|
+
gem.homepage = "http://astrails.com/opensource/server-blender"
|
20
|
+
gem.authors = ["Vitaly Kushner"]
|
21
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
22
|
+
gem.add_development_dependency "yard", ">= 0"
|
23
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
24
|
+
end
|
25
|
+
Jeweler::GemcutterTasks.new
|
26
|
+
rescue LoadError
|
27
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'spec/rake/spectask'
|
31
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
32
|
+
spec.libs << 'lib' << 'spec'
|
33
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
34
|
+
end
|
35
|
+
|
36
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
37
|
+
spec.libs << 'lib' << 'spec'
|
38
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
39
|
+
spec.rcov = true
|
40
|
+
end
|
41
|
+
|
42
|
+
task :spec => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :spec
|
45
|
+
|
46
|
+
begin
|
47
|
+
require 'yard'
|
48
|
+
YARD::Rake::YardocTask.new
|
49
|
+
rescue LoadError
|
50
|
+
task :yardoc do
|
51
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
52
|
+
end
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.8
|
data/bin/blender
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(File.join(__FILE__, "../../lib/blender"))
|
4
|
+
include Blender
|
5
|
+
|
6
|
+
# commands are just ruby scripts in lib/blender/cli
|
7
|
+
COMMANDS_DIR = File.expand_path("lib/blender/cli", Blender::ROOT)
|
8
|
+
COMMANDS = Dir["#{COMMANDS_DIR}/*rb"].map {|f| File.basename(f).split(".").first}
|
9
|
+
|
10
|
+
command = ARGV.shift
|
11
|
+
unless command && COMMANDS.include?(command)
|
12
|
+
abort <<-USAGE
|
13
|
+
Usage: blender COMMAND [OPTIONS]
|
14
|
+
|
15
|
+
Available commands: #{COMMANDS * " "}
|
16
|
+
Run "blender COMMAND -h" to get help about a command
|
17
|
+
USAGE
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'optparse'
|
21
|
+
require File.expand_path(File.join(__FILE__, "../../lib/blender/cli/", command))
|
data/files/bootstrap.sh
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
#!/bin/bash -eu
|
2
|
+
|
3
|
+
# log both to the 'real' stdout and into the log
|
4
|
+
function log()
|
5
|
+
{
|
6
|
+
echo "************* $@"
|
7
|
+
echo "************* $@" >&3
|
8
|
+
}
|
9
|
+
|
10
|
+
trap "log FAILED" EXIT
|
11
|
+
|
12
|
+
function banner()
|
13
|
+
{
|
14
|
+
cat <<_
|
15
|
+
Bootstraping blender...
|
16
|
+
Date: `date`
|
17
|
+
Hostname: `hostname`
|
18
|
+
System: `uname -a`
|
19
|
+
_
|
20
|
+
}
|
21
|
+
|
22
|
+
function setup_node()
|
23
|
+
{
|
24
|
+
if [ -n "${NODE:-}" ]; then
|
25
|
+
echo SET NODE: $NODE
|
26
|
+
echo $NODE > /etc/node
|
27
|
+
fi
|
28
|
+
}
|
29
|
+
|
30
|
+
function setup_hostname()
|
31
|
+
{
|
32
|
+
if [ -n "${HOSTNAME:-}" ]; then
|
33
|
+
echo SET HOSTNAME: $HOSTNAME
|
34
|
+
echo $HOSTNAME > /etc/hostname
|
35
|
+
hostname $HOSTNAME
|
36
|
+
fi
|
37
|
+
}
|
38
|
+
|
39
|
+
# initialize blender directory and redirect output to the log file
|
40
|
+
function blender_init()
|
41
|
+
{
|
42
|
+
mkdir -p /var/lib/blender/{recipes,logs,tmp}
|
43
|
+
chmod 0700 /var/lib/blender/
|
44
|
+
|
45
|
+
# save stdout into fd 3
|
46
|
+
exec 3>&1
|
47
|
+
|
48
|
+
# redirect stdout/error to the log
|
49
|
+
if [ -n "${TRACE:-}" ]; then
|
50
|
+
exec 1 | tee -a /var/lib/blender/logs/blender-bootstrap.log
|
51
|
+
else
|
52
|
+
exec 1>> /var/lib/blender/logs/blender-bootstrap.log
|
53
|
+
fi
|
54
|
+
exec 2>&1
|
55
|
+
|
56
|
+
cd /tmp
|
57
|
+
# lets log everything
|
58
|
+
set -x
|
59
|
+
}
|
60
|
+
|
61
|
+
|
62
|
+
function distribution()
|
63
|
+
{
|
64
|
+
echo "$DISTRIB_ID $DISTRIB_RELEASE"
|
65
|
+
}
|
66
|
+
|
67
|
+
function supported_version()
|
68
|
+
{
|
69
|
+
. /etc/lsb-release
|
70
|
+
|
71
|
+
case "`distribution`" in
|
72
|
+
"Ubuntu 10.04") true;;
|
73
|
+
*) false;;
|
74
|
+
esac
|
75
|
+
}
|
76
|
+
|
77
|
+
function check_version()
|
78
|
+
{
|
79
|
+
if ! supported_version; then
|
80
|
+
log "`distribution` is not supported"
|
81
|
+
exit
|
82
|
+
fi
|
83
|
+
}
|
84
|
+
|
85
|
+
export DEBIAN_FRONTEND=noninteractive
|
86
|
+
export DEBIAN_PRIORITY=critical
|
87
|
+
|
88
|
+
APT_OPTS="-qy -o DPkg::Options::=--force-confdef -o DPkg::Options::=--force-confnew"
|
89
|
+
|
90
|
+
# protect ec2-ami-tools from downgrade
|
91
|
+
function pin_ami_version()
|
92
|
+
{
|
93
|
+
cat <<-PREFS >/etc/apt/preferences
|
94
|
+
Package: ec2-ami-tools
|
95
|
+
Pin: version 1.3-34545
|
96
|
+
Pin-Priority: 500
|
97
|
+
PREFS
|
98
|
+
}
|
99
|
+
|
100
|
+
function apt_upgrade()
|
101
|
+
{
|
102
|
+
log "apt upgrade"
|
103
|
+
apt-get update
|
104
|
+
apt-get upgrade $APT_OPTS
|
105
|
+
apt-get autoremove $APT_OPTS
|
106
|
+
}
|
107
|
+
|
108
|
+
function apt_install()
|
109
|
+
{
|
110
|
+
apt-get install $APT_OPTS "$@"
|
111
|
+
}
|
112
|
+
|
113
|
+
function setup_etckeeper()
|
114
|
+
{
|
115
|
+
log "installing etckeeper"
|
116
|
+
apt_install git-core etckeeper
|
117
|
+
cp /etc/etckeeper/etckeeper.conf /etc/etckeeper/etckeeper.conf.orig
|
118
|
+
# etckeeper comes configured for bazr. use git instead.
|
119
|
+
(rm /etc/etckeeper/etckeeper.conf; awk "/^\s*VCS=/{sub(/.*/, \"VCS=git\")};{print}" > /etc/etckeeper/etckeeper.conf) < /etc/etckeeper/etckeeper.conf
|
120
|
+
etckeeper init
|
121
|
+
etckeeper commit "import during bootstrap" || true
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
function install_stuff()
|
127
|
+
{
|
128
|
+
log "installing required packages"
|
129
|
+
apt_install rsync build-essential zlib1g-dev libssl-dev libreadline5-dev wget bind9-host
|
130
|
+
}
|
131
|
+
|
132
|
+
function install_system_ruby()
|
133
|
+
{
|
134
|
+
log "installing system ruby"
|
135
|
+
apt_install ruby irb ruby-dev libopenssl-ruby
|
136
|
+
}
|
137
|
+
|
138
|
+
function install_system_rubygems()
|
139
|
+
{
|
140
|
+
log "installing system rubygems"
|
141
|
+
apt_install rubygems
|
142
|
+
}
|
143
|
+
|
144
|
+
function upgrade_rubygems()
|
145
|
+
{
|
146
|
+
log "upgrading rubygems"
|
147
|
+
gem install --no-rdoc --no-ri rubygems-update
|
148
|
+
update_rubygems
|
149
|
+
}
|
150
|
+
|
151
|
+
UPSTREAM_GEMS_VERSION=1.3.6
|
152
|
+
function install_custom_rubygems()
|
153
|
+
{
|
154
|
+
log "installing custom rubygems"
|
155
|
+
# remove system rubygems if exist
|
156
|
+
apt-get remove -qy --purge rubygems
|
157
|
+
apt-get autoremove -qy
|
158
|
+
|
159
|
+
# download and install gems
|
160
|
+
cd /tmp
|
161
|
+
wget http://production.cf.rubygems.org/rubygems/rubygems-$UPSTREAM_GEMS_VERSION.tgz
|
162
|
+
tar xfz rubygems-$UPSTREAM_GEMS_VERSION.tgz
|
163
|
+
pushd rubygems-$UPSTREAM_GEMS_VERSION
|
164
|
+
ruby setup.rb --no-rdoc --no-ri
|
165
|
+
ln -sfn /usr/bin/gem1.8 /usr/bin/gem
|
166
|
+
}
|
167
|
+
|
168
|
+
function install_puppet()
|
169
|
+
{
|
170
|
+
log "installing puppet"
|
171
|
+
gem install --no-rdoc --no-ri shadow_puppet -v 0.3.2
|
172
|
+
gem install --no-rdoc --no-ri ruby-debug
|
173
|
+
}
|
174
|
+
|
175
|
+
# adds /var/lib/gems/1.8/bin to paths. only needed with the system (debian) braindead gems
|
176
|
+
|
177
|
+
function add_gems_to_system_path()
|
178
|
+
{
|
179
|
+
log "fixing system path"
|
180
|
+
## # default /etc/login.defs
|
181
|
+
## ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
182
|
+
## ENV_PATH PATH=/usr/local/bin:/usr/bin:/bin:/usr/games
|
183
|
+
## # default /etc/environment
|
184
|
+
## PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
|
185
|
+
##
|
186
|
+
## When loggin-in over SSH /etc/environment path is active
|
187
|
+
## When doing "su - xxx" - /etc/login.defs path is active
|
188
|
+
|
189
|
+
etckeeper commit "before PATH update" || true
|
190
|
+
|
191
|
+
ENV_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/var/lib/gems/1.8/bin
|
192
|
+
USER_PATH=/usr/local/bin:/usr/bin:/bin:/usr/games:/var/lib/gems/1.8/bin
|
193
|
+
ROOT_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/var/lib/gems/1.8/bin
|
194
|
+
|
195
|
+
cat <<-ENV >/etc/environment
|
196
|
+
PATH="$ENV_PATH"
|
197
|
+
ENV
|
198
|
+
|
199
|
+
( rm /etc/login.defs; awk "/^\s*ENV_SUPATH/{sub(/.*/, \"ENV_SUPATH PATH=$ROOT_PATH\")};/^\s*ENV_PATH/{sub(/.*/, \"ENV_PATH PATH=$USER_PATH\")};{print}" > /etc/login.defs ) < /etc/login.defs
|
200
|
+
|
201
|
+
etckeeper commit "after PATH update"
|
202
|
+
}
|
203
|
+
|
204
|
+
#########################################################
|
205
|
+
#########################################################
|
206
|
+
|
207
|
+
banner
|
208
|
+
|
209
|
+
blender_init
|
210
|
+
|
211
|
+
setup_node
|
212
|
+
setup_hostname
|
213
|
+
|
214
|
+
check_version
|
215
|
+
pin_ami_version
|
216
|
+
apt_upgrade
|
217
|
+
setup_etckeeper
|
218
|
+
install_stuff
|
219
|
+
install_system_ruby
|
220
|
+
|
221
|
+
if [[ "${USE_SYSTEM_GEMS:-y}" == "y" ]]; then
|
222
|
+
install_system_rubygems
|
223
|
+
add_gems_to_system_path
|
224
|
+
else
|
225
|
+
install_custom_rubygems
|
226
|
+
upgrade_rubygems
|
227
|
+
# upstream rubygems install executables into /usr/bin so no need to fix the path
|
228
|
+
fi
|
229
|
+
|
230
|
+
|
231
|
+
gem install rdoc # needed by most gems
|
232
|
+
|
233
|
+
install_puppet
|
234
|
+
|
235
|
+
date > /etc/bootstraped_at
|
236
|
+
etckeeper commit "bootstrapped"
|
237
|
+
|
238
|
+
trap - EXIT
|
239
|
+
|
240
|
+
echo COMPLETED
|
@@ -0,0 +1,44 @@
|
|
1
|
+
options = {
|
2
|
+
:system_gems => 'y'
|
3
|
+
}
|
4
|
+
OptionParser.new do |opts|
|
5
|
+
opts.banner = "Usage: blender init [OPTIONS] HOST"
|
6
|
+
opts.separator ""
|
7
|
+
opts.separator "Common options:"
|
8
|
+
|
9
|
+
opts.on("-u", "--upstream-gems", "don't use the system gems, download and install upstream version instead") do
|
10
|
+
options[:system_gems] = 'n'
|
11
|
+
end
|
12
|
+
|
13
|
+
opts.on("-N", "--node NODE", "force NODE as the current nodename") do |val|
|
14
|
+
options[:node] = val
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("-t", "--trace", "dump trace to the stdout") do |val|
|
18
|
+
options[:trace] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("-H", "--hostname HOSTNAME", "set HOSTNAME") do |val|
|
22
|
+
options[:hostname] = val
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("-h", "--help", "Show this message") do
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
end.parse!
|
31
|
+
|
32
|
+
abort("please provide a hostname") unless host = ARGV.shift
|
33
|
+
|
34
|
+
extra=""
|
35
|
+
extra << " TRACE=1" if options[:trace]
|
36
|
+
extra << " HOSTNAME=#{options[:hostname]}" if options[:hostname]
|
37
|
+
extra << " NODE=#{options[:node]}" if options[:node]
|
38
|
+
|
39
|
+
def run(*cmd)
|
40
|
+
puts ">> #{cmd * ' '}"
|
41
|
+
system(*cmd)
|
42
|
+
end
|
43
|
+
|
44
|
+
run "cat files/bootstrap.sh | ssh #{host} USE_SYSTEM_GEMS=#{options[:system_gems]}#{extra} /bin/bash -eu"
|
@@ -0,0 +1,71 @@
|
|
1
|
+
options = {
|
2
|
+
:recipe => 'default'
|
3
|
+
}
|
4
|
+
opts = OptionParser.new do |opts|
|
5
|
+
opts.banner = "Usage: blender mix [OPTIONS] [DIR] HOST"
|
6
|
+
opts.separator "Options:"
|
7
|
+
|
8
|
+
opts.on("-r", "--recipe RECIPE", "('default' will be used if RECIPE not specified") do |val|
|
9
|
+
options[:recipe] = val
|
10
|
+
end
|
11
|
+
|
12
|
+
opts.on("-N", "--node NODE", "force NODE as the current nodename") do |val|
|
13
|
+
options[:node] = val
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on("-R", "--roles ROLES", "comma delimited list of roles that should execute") do |val|
|
17
|
+
options[:roles] = val
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.separator ""
|
21
|
+
opts.separator "Common options:"
|
22
|
+
|
23
|
+
opts.on("-h", "--help", "Show this message") do
|
24
|
+
puts opts
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.separator ""
|
29
|
+
opts.separator "Notes:"
|
30
|
+
opts.separator ' "." used if DIR not specified'
|
31
|
+
|
32
|
+
end
|
33
|
+
opts.parse!
|
34
|
+
|
35
|
+
dir = ARGV.shift
|
36
|
+
host = ARGV.shift
|
37
|
+
abort("unexpected: #{ARGV*" "}\n#{opts}") unless ARGV.empty?
|
38
|
+
if host.nil?
|
39
|
+
host = dir
|
40
|
+
dir = "."
|
41
|
+
end
|
42
|
+
|
43
|
+
abort(opts.to_s) unless dir && host
|
44
|
+
|
45
|
+
unless File.directory?(dir)
|
46
|
+
puts "#{dir} is not a directory"
|
47
|
+
abort(opts.to_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
File.file?(File.join(dir, recipe = options[:recipe])) ||
|
51
|
+
File.file?(File.join(dir, recipe = "#{options[:recipe]}.rb")) ||
|
52
|
+
abort("recipe #{recipe} not found\n#{opts}")
|
53
|
+
|
54
|
+
WORK_DIR = "/var/lib/blender/recipes"
|
55
|
+
LOCAL_MANIFEST_DIR = File.expand_path("../../manifest", __FILE__)
|
56
|
+
REMOTE_MANIFEST_DIR = "/var/lib/blender/manifest"
|
57
|
+
ROOT_MANIFEST = File.join(REMOTE_MANIFEST_DIR, "root.rb")
|
58
|
+
|
59
|
+
def run(*cmd)
|
60
|
+
puts ">> #{cmd * ' '}"
|
61
|
+
system(*cmd)
|
62
|
+
end
|
63
|
+
|
64
|
+
run("rsync -azP --delete --exclude '.*' #{LOCAL_MANIFEST_DIR}/ #{host}:#{REMOTE_MANIFEST_DIR}") &&
|
65
|
+
run("rsync -azP --delete --exclude '.*' --exclude other #{dir}/ #{host}:#{WORK_DIR}") &&
|
66
|
+
|
67
|
+
extra=""
|
68
|
+
extra << " NODE=#{options[:node]}" if options[:node]
|
69
|
+
extra << " ROLES=#{options[:roles]}" if options[:roles]
|
70
|
+
|
71
|
+
run("ssh", host, "echo 'Running Puppet [recipe: #{recipe}]...';cd #{WORK_DIR} && RECIPE=#{recipe} #{extra} shadow_puppet #{ROOT_MANIFEST}")
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'pp'
|
2
|
+
options = {}
|
3
|
+
|
4
|
+
AMI_64 = "ami-55739e3c"
|
5
|
+
AMI_32 = "ami-bb709dd2"
|
6
|
+
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: blender start [OPTIONS] [-- [ec2run options]]"
|
9
|
+
opts.separator "Options:"
|
10
|
+
|
11
|
+
opts.on("--ami AMI",
|
12
|
+
"use specified AMI instead of the default one.",
|
13
|
+
"If you don't specify your own AMI blender will choose a defaule one:",
|
14
|
+
"* #{AMI_32} for 32 bits",
|
15
|
+
"* #{AMI_64} for 64 bits",
|
16
|
+
"You can change the defaults by writing your own AMIs",
|
17
|
+
"into ~/.blender/ami and ~/.blender/ami64 files",
|
18
|
+
" "
|
19
|
+
) do |val|
|
20
|
+
options[:ami] = val
|
21
|
+
end
|
22
|
+
opts.on("--key KEY",
|
23
|
+
"use KEY when starting instance. KEY should already be generated.",
|
24
|
+
"If you don't specify a KEY blender will try to use the key from your EC2 account",
|
25
|
+
"Note: There must be only ONE key on the account for it to work. ",
|
26
|
+
" "
|
27
|
+
) do |val|
|
28
|
+
options[:key] = val
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("--64", "use 64 bit default AMI. This does nothing if you specify your own AMI") do
|
32
|
+
options[64] = true
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-n", "--dry-run", "Don't do anything, just print the command line to be executed") do |val|
|
36
|
+
options[:dry] = true
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.separator "\nCommon options:"
|
40
|
+
|
41
|
+
opts.on("-h", "--help", "Show this message") do
|
42
|
+
puts opts
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on_tail <<-EXAMPLE
|
47
|
+
|
48
|
+
Example:
|
49
|
+
|
50
|
+
# start a 64bit instance with default options
|
51
|
+
blender start -64
|
52
|
+
|
53
|
+
# start with a custom ami
|
54
|
+
blender start --ami ami-2d4aa444
|
55
|
+
|
56
|
+
# start with passing arguments to ec2run: use security group default+test
|
57
|
+
blender start -- -g default -g test
|
58
|
+
EXAMPLE
|
59
|
+
|
60
|
+
|
61
|
+
end.parse!
|
62
|
+
|
63
|
+
def default_ami(options)
|
64
|
+
name = options[64] ? "~/.blender/ami64" : "~/.blender/ami"
|
65
|
+
ami = File.read(File.expand_path(name)) rescue nil
|
66
|
+
ami = options[64] ? AMI_64 : AMI_32 if ami.nil? || ami.empty?
|
67
|
+
ami
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_key(options)
|
71
|
+
keys = `ec2dkey`.strip.split("\n")
|
72
|
+
abort("too many keys") if keys.length > 1
|
73
|
+
abort("can't find any keys") if keys.length != 1
|
74
|
+
keys.first.split("\t")[1] || raise("invalid key")
|
75
|
+
end
|
76
|
+
|
77
|
+
ami = options[:ami] || default_ami(options)
|
78
|
+
key = options[:key] || default_key(options)
|
79
|
+
|
80
|
+
cmd = ["ec2run", ami, "-k", key, *ARGV]
|
81
|
+
puts cmd * " "
|
82
|
+
system(*cmd) unless options[:dry]
|
data/lib/blender.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{server-blender}
|
8
|
+
s.version = "0.0.8"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Vitaly Kushner"]
|
12
|
+
s.date = %q{2010-06-15}
|
13
|
+
s.default_executable = %q{blender}
|
14
|
+
s.description = %q{Boostrap and manage servers with shadow_puppet
|
15
|
+
|
16
|
+
Server Blender tries to be a fairly minimal wrapper around shadow_puppet
|
17
|
+
http://github.com/railsmachine/shadow_puppet
|
18
|
+
|
19
|
+
shadow_puppet is a Ruby interface to Puppet's manifests.
|
20
|
+
http://reductivelabs.com/products/puppet/
|
21
|
+
}
|
22
|
+
s.email = %q{vitaly@astrails.com}
|
23
|
+
s.executables = ["blender"]
|
24
|
+
s.extra_rdoc_files = [
|
25
|
+
"LICENSE",
|
26
|
+
"README.markdown"
|
27
|
+
]
|
28
|
+
s.files = [
|
29
|
+
".braids",
|
30
|
+
".document",
|
31
|
+
".gitignore",
|
32
|
+
"LICENSE",
|
33
|
+
"PLAN",
|
34
|
+
"README.markdown",
|
35
|
+
"Rakefile",
|
36
|
+
"VERSION",
|
37
|
+
"bin/blender",
|
38
|
+
"files/bootstrap.sh",
|
39
|
+
"lib/blender.rb",
|
40
|
+
"lib/blender/cli/init.rb",
|
41
|
+
"lib/blender/cli/mix.rb",
|
42
|
+
"lib/blender/cli/start.rb",
|
43
|
+
"server-blender.gemspec",
|
44
|
+
"spec/server-blender_spec.rb",
|
45
|
+
"spec/spec.opts",
|
46
|
+
"spec/spec_helper.rb",
|
47
|
+
"vendor/server-blender-manifests/.gitignore",
|
48
|
+
"vendor/server-blender-manifests/LICENSE",
|
49
|
+
"vendor/server-blender-manifests/README.markdown",
|
50
|
+
"vendor/server-blender-manifests/Rakefile",
|
51
|
+
"vendor/server-blender-manifests/VERSION",
|
52
|
+
"vendor/server-blender-manifests/lib/blender/manifest/init.rb",
|
53
|
+
"vendor/server-blender-manifests/lib/blender/manifest/mixer.rb",
|
54
|
+
"vendor/server-blender-manifests/lib/blender/manifest/nodes.rb",
|
55
|
+
"vendor/server-blender-manifests/lib/blender/manifest/roles.rb",
|
56
|
+
"vendor/server-blender-manifests/lib/blender/manifest/root.rb",
|
57
|
+
"vendor/server-blender-manifests/server-blender-manifest.gemspec",
|
58
|
+
"vendor/server-blender-manifests/spec/spec.opts",
|
59
|
+
"vendor/server-blender-manifests/spec/spec_helper.rb"
|
60
|
+
]
|
61
|
+
s.homepage = %q{http://astrails.com/opensource/server-blender}
|
62
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
63
|
+
s.require_paths = ["lib"]
|
64
|
+
s.rubygems_version = %q{1.3.6}
|
65
|
+
s.summary = %q{Server provisioning and configuration management tool}
|
66
|
+
s.test_files = [
|
67
|
+
"spec/server-blender_spec.rb",
|
68
|
+
"spec/spec_helper.rb"
|
69
|
+
]
|
70
|
+
|
71
|
+
if s.respond_to? :specification_version then
|
72
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
73
|
+
s.specification_version = 3
|
74
|
+
|
75
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
76
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
77
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
78
|
+
else
|
79
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
80
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
81
|
+
end
|
82
|
+
else
|
83
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
84
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
## MISC
|
2
|
+
pkg
|
3
|
+
tags
|
4
|
+
.yardoc
|
5
|
+
|
6
|
+
## MAC OS
|
7
|
+
.DS_Store
|
8
|
+
|
9
|
+
## TEXTMATE
|
10
|
+
*.tmproj
|
11
|
+
tmtags
|
12
|
+
|
13
|
+
## EMACS
|
14
|
+
*~
|
15
|
+
\#*
|
16
|
+
.\#*
|
17
|
+
|
18
|
+
## VIM
|
19
|
+
*.swp
|
20
|
+
|
21
|
+
## PROJECT::GENERAL
|
22
|
+
coverage
|
23
|
+
rdoc
|
24
|
+
pkg
|
25
|
+
|
26
|
+
## PROJECT::SPECIFIC
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Vitaly Kushner
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# server-blender-manifest
|
2
|
+
|
3
|
+
This gem is part of the [server-blender](http://astrails.com/opensource/server-blender) family.
|
4
|
+
|
5
|
+
It contains server-side root manifest implementation for blender recipes. See server-blender for more information.
|
6
|
+
|
7
|
+
* Home: [http://astrails.com/opensource/server-blender](http://astrails.com/opensource/server-blender)
|
8
|
+
* Code: [http://github.com/astrails/server-blender-manifest](http://github.com/astrails/server-blender-manifest)
|
9
|
+
* Blog: [http://blog.astrails.com/server-blender](http://blog.astrails.com/server-blender)
|
10
|
+
|
11
|
+
## Note on Patches/Pull Requests
|
12
|
+
|
13
|
+
* Fork the project.
|
14
|
+
* Make your feature addition or bug fix.
|
15
|
+
* Add tests for it. This is important so I don't break it in a
|
16
|
+
future version unintentionally.
|
17
|
+
* Commit, do not mess with rakefile, version, or history.
|
18
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
19
|
+
* Send me a pull request. Bonus points for topic branches.
|
20
|
+
|
21
|
+
## Copyright
|
22
|
+
|
23
|
+
Copyright (c) 2010 Vitaly Kushner. See LICENSE for details.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "server-blender-manifest"
|
8
|
+
gem.summary = %Q{server-side root manifest implementation for server-blender}
|
9
|
+
gem.description = <<-DESC
|
10
|
+
This gem is part of the server-blender family (http://astrails.com/opensource/server-blender)
|
11
|
+
It contains server-side root manifest implementation for blender recipes. See server-blender for more information.
|
12
|
+
DESC
|
13
|
+
gem.email = "vitaly@astrails.com"
|
14
|
+
gem.homepage = "http://astrails.com/opensource/server-blender"
|
15
|
+
gem.authors = ["Vitaly Kushner"]
|
16
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
17
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'spec/rake/spectask'
|
25
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
+
spec.libs << 'lib' << 'spec'
|
27
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
|
30
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
31
|
+
spec.libs << 'lib' << 'spec'
|
32
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
+
spec.rcov = true
|
34
|
+
end
|
35
|
+
|
36
|
+
task :spec => :check_dependencies
|
37
|
+
|
38
|
+
task :default => :spec
|
39
|
+
|
40
|
+
# documentaion is included in the parent server-blender gem
|
@@ -0,0 +1 @@
|
|
1
|
+
0.0.8
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Blender::Manifest::Init
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
recipe :create_blender_directories
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
# create blender directories
|
9
|
+
# @return dependency ref for the direcotires creation
|
10
|
+
def create_blender_directories
|
11
|
+
@create_blender_directories ||=
|
12
|
+
begin
|
13
|
+
dep = directory "/var/lib/blender", :mode => 0700
|
14
|
+
dep = directory "/var/lib/blender/logs", :require => dep
|
15
|
+
dep = directory "/var/lib/blender/tmp", :require => dep
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return dependency for blender directories
|
20
|
+
def builder_deps
|
21
|
+
create_blender_directories
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Blender::Manifest::Mixer
|
2
|
+
# mixes recipe module
|
3
|
+
#
|
4
|
+
# The purpose is to make the mixing of recipes cleaner and easier on the eyes :)
|
5
|
+
# i.e. instead of
|
6
|
+
# require 'foo'
|
7
|
+
# include Blender::Recipes::Foo
|
8
|
+
# require 'bar'
|
9
|
+
# include Blender::Recipes::Bar
|
10
|
+
# you can just
|
11
|
+
# mix :foo, :bar
|
12
|
+
# @param [[String, Symbol, Module]] recipes to mix
|
13
|
+
def mix(*recipes)
|
14
|
+
|
15
|
+
recipes.each do |recipe|
|
16
|
+
|
17
|
+
next if Root.mixed_recipes.include?(recipe)
|
18
|
+
Root.mixed_recipes << recipe
|
19
|
+
|
20
|
+
case recipe
|
21
|
+
when String, Symbol
|
22
|
+
require recipe.to_s
|
23
|
+
mixin = "Blender::Recipes::#{recipe.to_s.camelize}".constantize
|
24
|
+
when Module
|
25
|
+
mixin = recipe
|
26
|
+
else
|
27
|
+
raise "Expecting String, Symbol or Module. don't know what do do with #{recipe.inspect}"
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "MIX: #{mixin}"
|
31
|
+
::Root.send :include, mixin
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# This module encapsulates nodes handeling
|
2
|
+
# Nodes can be declared both on a class level and inside a recipe
|
3
|
+
# When defining a node an 'id' is associated with its hostname
|
4
|
+
# and the node can later be reffered by this id (for example
|
5
|
+
# to get its ip)
|
6
|
+
module Blender::Manifest::Nodes
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.send :extend, self
|
10
|
+
end
|
11
|
+
|
12
|
+
# this holds the map from host ids to hostnames
|
13
|
+
@@internal_hostnames = {}
|
14
|
+
@@external_hostnames = {}
|
15
|
+
|
16
|
+
# returns hostname by id or local host's name if the id is nil
|
17
|
+
def hostname(id = nil, external = false)
|
18
|
+
if id
|
19
|
+
(external ? @@external_hostnames : @@internal_hostnames)[id]
|
20
|
+
else
|
21
|
+
external ? Facter.fqdn : Facter.hostname
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns id of the node we are running at
|
26
|
+
# Note: will ONLY return non-nil value after (or during) node definition
|
27
|
+
# unless node is forced by environment NODE variable or /etc/node file
|
28
|
+
def current_node
|
29
|
+
node = ENV['NODE'] ||
|
30
|
+
(File.exists?("/etc/node") && File.read("/etc/node").strip) ||
|
31
|
+
@@internal_hostnames.index(hostname) ||
|
32
|
+
@@external_hostnames.index(hostname(nil, true))
|
33
|
+
node && node.to_sym
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return true if we are running on the node with the given `id`
|
37
|
+
def current_node?(id)
|
38
|
+
current_node == id.to_sym
|
39
|
+
end
|
40
|
+
|
41
|
+
# resolves host name using 'host' executable
|
42
|
+
# @return host's IP by its name or nil if not found
|
43
|
+
def host_ip(name)
|
44
|
+
res = `host #{name}`.split("\n").grep(/has address/).first
|
45
|
+
res && res.split.last
|
46
|
+
end
|
47
|
+
|
48
|
+
# define node and conditionally execute code block only on the specific node
|
49
|
+
# Note: can be called multiple times without internal_name and external_name parameters
|
50
|
+
# in which case will only do the conditional execution
|
51
|
+
# @param [Symbol, String] id of the host to define or test for
|
52
|
+
# @param [String] internal_name short hostname for the host
|
53
|
+
# @param [String] external_name full dns hostname for the host
|
54
|
+
# @example
|
55
|
+
# node :app, "host5", "host5.serverfarm2.localdomain" do
|
56
|
+
# ...
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# node :app do
|
60
|
+
# ...
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
def node(id, internal_name = nil, external_name = internal_name)
|
64
|
+
return if false == internal_name # can be used to temporary 'disable' host's definition
|
65
|
+
# like:
|
66
|
+
# host :app2, false do .. end
|
67
|
+
@@internal_hostnames[id] = internal_name if internal_name
|
68
|
+
@@external_hostnames[id] = external_name if external_name
|
69
|
+
|
70
|
+
if block_given? && current_node?(id)
|
71
|
+
puts "NODE: #{id} / #{current_node}"
|
72
|
+
@node = id
|
73
|
+
yield
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# find out node addr. try to use external, then internal, then the host id to determine ip
|
78
|
+
# @param [Symbol, String] id id of the host to resolve
|
79
|
+
def addr(id)
|
80
|
+
[hostname(id, true).to_s, hostname(id).to_s, id.to_s].each do |name|
|
81
|
+
ip = host_ip(name)
|
82
|
+
return ip if ip
|
83
|
+
end
|
84
|
+
|
85
|
+
# if all else fails, we should still be able to address the current node
|
86
|
+
current_node?(id) ? "127.0.0.1" : nil
|
87
|
+
end
|
88
|
+
|
89
|
+
# same as addr but throws exception if IP can't be found
|
90
|
+
def addr!(id)
|
91
|
+
addr(id) or raise "Can't find address for '#{id}'"
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Blender::Manifest::Roles
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.send :extend, self
|
5
|
+
end
|
6
|
+
|
7
|
+
# A very simple mechanism to define roles
|
8
|
+
#
|
9
|
+
# Roles to accept can be defined from environment, /etc/roles file
|
10
|
+
# or can be explicitly defined like 'roles xxx, yyy'
|
11
|
+
# usually the 'roles a,b,c' call will come inside of
|
12
|
+
# a `node` block and so will be conditionally executed depending on the
|
13
|
+
# running host
|
14
|
+
|
15
|
+
def current_roles
|
16
|
+
@current_roles ||=
|
17
|
+
if ENV['ROLES']
|
18
|
+
ENV['ROLES'].split(",")
|
19
|
+
elsif File.exists?("/etc/roles")
|
20
|
+
File.read("/etc/roles").strip.split
|
21
|
+
else
|
22
|
+
[]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# ADDS roles to the currently defined roles
|
27
|
+
def roles *roles
|
28
|
+
current_roles.concat(roles.map {|r| r.to_s})
|
29
|
+
end
|
30
|
+
|
31
|
+
# conditionally runs the code block if the role 'r' is
|
32
|
+
# currently defined
|
33
|
+
def role r
|
34
|
+
if block_given? && current_roles.include?(r.to_s)
|
35
|
+
puts "ROLE: #{r}"
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'ruby-debug'
|
2
|
+
$: << File.dirname(__FILE__) # FIXME: remove?
|
3
|
+
|
4
|
+
module Blender
|
5
|
+
module Manifest; end
|
6
|
+
module Recipes; end
|
7
|
+
end
|
8
|
+
require 'init'
|
9
|
+
require 'nodes'
|
10
|
+
require 'roles'
|
11
|
+
require 'mixer'
|
12
|
+
|
13
|
+
class Root < ::ShadowPuppet::Manifest
|
14
|
+
include Blender::Manifest::Init
|
15
|
+
include Blender::Manifest::Nodes
|
16
|
+
include Blender::Manifest::Roles
|
17
|
+
|
18
|
+
@@mixed_recipes = []
|
19
|
+
def self.mixed_recipes
|
20
|
+
@@mixed_recipes
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute_user_recipe
|
24
|
+
raise "no RECIPE to execute" unless recipe = ENV['RECIPE']
|
25
|
+
|
26
|
+
code = open(recipe).read
|
27
|
+
instance_eval(code, recipe)
|
28
|
+
end
|
29
|
+
recipe :execute_user_recipe
|
30
|
+
end
|
31
|
+
|
32
|
+
include Blender::Manifest::Mixer
|
33
|
+
|
34
|
+
# "standard" recipe directories
|
35
|
+
$: << "recipes" << "recipes/astrails" << "lib/astrails/blender/recipes"
|
36
|
+
|
37
|
+
# add all libs in the ./vendor directory to the path
|
38
|
+
$:.concat Dir["vendor/*/"]
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{server-blender-manifest}
|
8
|
+
s.version = "0.0.8"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Vitaly Kushner"]
|
12
|
+
s.date = %q{2010-06-15}
|
13
|
+
s.description = %q{This gem is part of the server-blender family (http://astrails.com/opensource/server-blender)
|
14
|
+
It contains server-side root manifest implementation for blender recipes. See server-blender for more information.
|
15
|
+
}
|
16
|
+
s.email = %q{vitaly@astrails.com}
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.markdown"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".gitignore",
|
23
|
+
"LICENSE",
|
24
|
+
"README.markdown",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"lib/blender/manifest/init.rb",
|
28
|
+
"lib/blender/manifest/mixer.rb",
|
29
|
+
"lib/blender/manifest/nodes.rb",
|
30
|
+
"lib/blender/manifest/roles.rb",
|
31
|
+
"lib/blender/manifest/root.rb",
|
32
|
+
"server-blender-manifest.gemspec",
|
33
|
+
"spec/spec.opts",
|
34
|
+
"spec/spec_helper.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://astrails.com/opensource/server-blender}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.3.6}
|
40
|
+
s.summary = %q{server-side root manifest implementation for server-blender}
|
41
|
+
s.test_files = [
|
42
|
+
"spec/spec_helper.rb"
|
43
|
+
]
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
|
+
s.specification_version = 3
|
48
|
+
|
49
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: server-blender
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
version: 0.0.8
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Vitaly Kushner
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-06-15 00:00:00 +03:00
|
18
|
+
default_executable: blender
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
31
|
+
version: 1.2.9
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: yard
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
description: |
|
47
|
+
Boostrap and manage servers with shadow_puppet
|
48
|
+
|
49
|
+
Server Blender tries to be a fairly minimal wrapper around shadow_puppet
|
50
|
+
http://github.com/railsmachine/shadow_puppet
|
51
|
+
|
52
|
+
shadow_puppet is a Ruby interface to Puppet's manifests.
|
53
|
+
http://reductivelabs.com/products/puppet/
|
54
|
+
|
55
|
+
email: vitaly@astrails.com
|
56
|
+
executables:
|
57
|
+
- blender
|
58
|
+
extensions: []
|
59
|
+
|
60
|
+
extra_rdoc_files:
|
61
|
+
- LICENSE
|
62
|
+
- README.markdown
|
63
|
+
files:
|
64
|
+
- .braids
|
65
|
+
- .document
|
66
|
+
- .gitignore
|
67
|
+
- LICENSE
|
68
|
+
- PLAN
|
69
|
+
- README.markdown
|
70
|
+
- Rakefile
|
71
|
+
- VERSION
|
72
|
+
- bin/blender
|
73
|
+
- files/bootstrap.sh
|
74
|
+
- lib/blender.rb
|
75
|
+
- lib/blender/cli/init.rb
|
76
|
+
- lib/blender/cli/mix.rb
|
77
|
+
- lib/blender/cli/start.rb
|
78
|
+
- server-blender.gemspec
|
79
|
+
- spec/server-blender_spec.rb
|
80
|
+
- spec/spec.opts
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- vendor/server-blender-manifests/.gitignore
|
83
|
+
- vendor/server-blender-manifests/LICENSE
|
84
|
+
- vendor/server-blender-manifests/README.markdown
|
85
|
+
- vendor/server-blender-manifests/Rakefile
|
86
|
+
- vendor/server-blender-manifests/VERSION
|
87
|
+
- vendor/server-blender-manifests/lib/blender/manifest/init.rb
|
88
|
+
- vendor/server-blender-manifests/lib/blender/manifest/mixer.rb
|
89
|
+
- vendor/server-blender-manifests/lib/blender/manifest/nodes.rb
|
90
|
+
- vendor/server-blender-manifests/lib/blender/manifest/roles.rb
|
91
|
+
- vendor/server-blender-manifests/lib/blender/manifest/root.rb
|
92
|
+
- vendor/server-blender-manifests/server-blender-manifest.gemspec
|
93
|
+
- vendor/server-blender-manifests/spec/spec.opts
|
94
|
+
- vendor/server-blender-manifests/spec/spec_helper.rb
|
95
|
+
has_rdoc: true
|
96
|
+
homepage: http://astrails.com/opensource/server-blender
|
97
|
+
licenses: []
|
98
|
+
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options:
|
101
|
+
- --charset=UTF-8
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
version: "0"
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
version: "0"
|
118
|
+
requirements: []
|
119
|
+
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 1.3.6
|
122
|
+
signing_key:
|
123
|
+
specification_version: 3
|
124
|
+
summary: Server provisioning and configuration management tool
|
125
|
+
test_files:
|
126
|
+
- spec/server-blender_spec.rb
|
127
|
+
- spec/spec_helper.rb
|