toquen 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +16 -6
- data/Rakefile +1 -1
- data/lib/toquen/bootstrapper.rb +15 -0
- data/lib/toquen/capistrano.rb +6 -47
- data/lib/toquen/local_writer.rb +22 -0
- data/lib/toquen/templates/ubuntu_bootstrap.erb +20 -0
- data/lib/toquen/version.rb +1 -1
- data/lib/toquen.rb +2 -0
- metadata +6 -3
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# Toquen
|
2
|
+
![A Toque](http://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/William_Orpen_Le_Chef_de_l%27H%C3%B4tel_Chatham%2C_Paris.jpg/97px-William_Orpen_Le_Chef_de_l%27H%C3%B4tel_Chatham%2C_Paris.jpg)
|
2
3
|
|
3
4
|
**Toquen** combines [Capistrano 3](http://www.capistranorb.com), [Chef](http://www.getchef.com), and [AWS instance tags](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) into one bundle of joy. Instance roles are stored in AWS tags and **Toquen** can suck those out, put them into data bags for chef, and create stages in capistrano. You can then selectively run chef on individual servers or whole roles that contain many servers with simple commands.
|
4
5
|
|
5
6
|
## Installation
|
7
|
+
Before beginning, you should already understand how [chef-solo](http://docs.opscode.com/chef_solo.html) works and have some cookbooks, roles defined, and at least a folder for data_bags (even if it's empty). The rest of this guide assumes you have these ready as well as an AWS PEM key and [access credentials](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html).
|
6
8
|
|
7
9
|
Generally, it's easiest if you start off in an empty directory. First, create a file named *Gemfile* that contains these lines:
|
8
10
|
|
@@ -30,7 +32,7 @@ Then, run:
|
|
30
32
|
|
31
33
|
$ cap update_roles
|
32
34
|
|
33
|
-
This will create a data_bag named *servers* that contains one item per server name, as well as create stages per server and role for use in capistrano.
|
35
|
+
This will create a data_bag named *servers* in your data_bags path that contains one item per server name, as well as create stages per server and role for use in capistrano.
|
34
36
|
|
35
37
|
## Server Bootstrapping
|
36
38
|
Bootstrapping a server will perform all of the following:
|
@@ -43,11 +45,15 @@ Bootstrapping a server will perform all of the following:
|
|
43
45
|
|
44
46
|
You can bootstrap a single server by using:
|
45
47
|
|
46
|
-
$ cap server-<server name>
|
48
|
+
$ cap server-<server name> bootstrap
|
47
49
|
|
48
|
-
Or a all the servers with a given role
|
50
|
+
Or a all the servers with a given role:
|
51
|
+
|
52
|
+
$ cap <role name> bootstrap
|
53
|
+
|
54
|
+
Or on all servers:
|
49
55
|
|
50
|
-
$ cap
|
56
|
+
$ cap all bootstrap
|
51
57
|
|
52
58
|
A lockfile is created after the first bootstrapping so that the full bootstrap process is only run once per server.
|
53
59
|
|
@@ -60,10 +66,14 @@ Or a all the servers with a given role with:
|
|
60
66
|
|
61
67
|
$ cap <role name> cook
|
62
68
|
|
69
|
+
Or on all servers:
|
70
|
+
|
71
|
+
$ cap all cook
|
72
|
+
|
63
73
|
## Updating Roles
|
64
|
-
If you change the roles of any servers you will need to run:
|
74
|
+
If you change the roles of any servers on AWS (or add any new ones) you will need to run:
|
65
75
|
|
66
|
-
$
|
76
|
+
$ cap update_roles
|
67
77
|
|
68
78
|
This will update the *servers* data_bag as well as the capistrano stages.
|
69
79
|
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require "bundler/gem_tasks"
|
|
2
2
|
require 'rdoc/task'
|
3
3
|
|
4
4
|
RDoc::Task.new("doc") { |rdoc|
|
5
|
-
rdoc.title = "Capistrano + AWS + Chef-Solo"
|
5
|
+
rdoc.title = "Toquen: Capistrano + AWS + Chef-Solo"
|
6
6
|
rdoc.rdoc_dir = 'docs'
|
7
7
|
rdoc.rdoc_files.include('README.md')
|
8
8
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Toquen
|
4
|
+
module Bootstrapper
|
5
|
+
def self.generate_script(host)
|
6
|
+
# host is available via the binding
|
7
|
+
hosttype = fetch(:hosttype, 'ubuntu')
|
8
|
+
path = File.expand_path("../templates/#{hosttype}_bootstrap.erb", __FILE__)
|
9
|
+
raise "Bootstrap process for #{hosttype} does not exist!" unless File.exists?(path)
|
10
|
+
rubygems_version = fetch(:rubygems_version, '2.1.11')
|
11
|
+
user = fetch(:ssh_options)[:user]
|
12
|
+
StringIO.new ERB.new(File.read(path)).result(binding)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/toquen/capistrano.rb
CHANGED
@@ -8,62 +8,21 @@ task :update_roles do
|
|
8
8
|
|
9
9
|
aws = Toquen::AWSProxy.new
|
10
10
|
aws.server_details.each do |details|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
16
|
-
details[:roles].each { |role| roles[role] += [details[:external_ip]] }
|
17
|
-
roles['all'] += [details[:external_ip]]
|
18
|
-
|
19
|
-
open("config/deploy/server-#{details[:name]}.rb", 'w') { |f|
|
20
|
-
f.write("# This file will be overwritten by toquen! Don't put anything here.\n")
|
21
|
-
f.write("set :stage, 'server-#{details[:name]}'.intern\n")
|
22
|
-
(details[:roles] + ["server-#{details[:name]}"]).each { |role|
|
23
|
-
f.write("role '#{role}'.intern, %w{#{details[:external_ip]}}\n")
|
24
|
-
}
|
25
|
-
f.write("set :filter, :roles => %w{server-#{details[:name]}}\n")
|
26
|
-
}
|
11
|
+
details[:roles].each { |role| roles[role] += [details] }
|
12
|
+
roles['all'] += [details]
|
13
|
+
Toquen::LocalWriter.create_databag_item details
|
14
|
+
Toquen::LocalWriter.create_stage "server-#{details[:name]}", [details]
|
27
15
|
end
|
28
16
|
|
29
|
-
roles.
|
30
|
-
open("config/deploy/#{name}.rb", 'w') { |f|
|
31
|
-
f.write("# This file will be overwritten by toquen! Don't put anything here.\n")
|
32
|
-
f.write("set :stage, '#{name}'.intern\n")
|
33
|
-
roles.each { |n,ips|
|
34
|
-
f.write("role '#{n}'.intern, %w{#{ips.reject(&:nil?).join(' ')}}\n")
|
35
|
-
}
|
36
|
-
f.write("set :filter, :roles => %w{#{name}}\n")
|
37
|
-
}
|
38
|
-
end
|
17
|
+
roles.each { |name, servers| Toquen::Writer.create_stage name, servers }
|
39
18
|
end
|
40
19
|
|
41
20
|
desc "bootstrap a server so that it can run chef"
|
42
21
|
task :bootstrap do
|
43
|
-
rgems = "rubygems-#{fetch(:rubygems_version, '2.1.11')}"
|
44
22
|
on roles(:all), in: :parallel do |host|
|
45
23
|
info "Bootstrapping #{host}..."
|
46
|
-
code = <<-EOF
|
47
|
-
#!/bin/bash
|
48
|
-
if [ -e "/home/#{fetch(:ssh_options)[:user]}/bootstrap.lock" ]; then exit 0; fi
|
49
|
-
DEBIAN_FRONTEND=noninteractive apt-get -y update
|
50
|
-
DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
|
51
|
-
DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
|
52
|
-
DEBIAN_FRONTEND=noninteractive apt-get -y install ruby1.9.3 ruby-dev automake make
|
53
|
-
update-alternatives --set ruby /usr/bin/ruby1.9.1
|
54
|
-
cd /usr/src
|
55
|
-
rm -rf rubygems*
|
56
|
-
wget -q http://production.cf.rubygems.org/rubygems/#{rgems}.tgz
|
57
|
-
tar -zxf #{rgems}.tgz
|
58
|
-
cd /usr/src/#{rgems}
|
59
|
-
ruby setup.rb
|
60
|
-
gem install --no-rdoc --no-ri chef bundler
|
61
|
-
touch /home/#{fetch(:ssh_options)[:user]}/bootstrap.lock
|
62
|
-
echo "Rebooting now, standby..."
|
63
|
-
reboot
|
64
|
-
EOF
|
65
24
|
fname = "/home/#{fetch(:ssh_options)[:user]}/bootstrap.sh"
|
66
|
-
upload!
|
25
|
+
upload! Toquen::Bootstrapper.generate_script(host), fname
|
67
26
|
sudo "sh #{fname}"
|
68
27
|
end
|
69
28
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Toquen
|
2
|
+
module LocalWriter
|
3
|
+
def self.create_databag_item(details)
|
4
|
+
open("#{fetch(:chef_data_bags_path)}/servers/#{details[:name]}.json", 'w') do |f|
|
5
|
+
f.write JSON.dump(details)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.create_stage(name, servers)
|
10
|
+
run_locally { info "Creating stage '#{name}' with servers: #{servers.map { |s| s[:name] }.join(', ')}" }
|
11
|
+
open("config/deploy/#{name}.rb", 'w') do |f|
|
12
|
+
f.write("# This file will be overwritten by toquen! Don't put anything here.\n")
|
13
|
+
f.write("set :stage, '#{name}'.intern\n")
|
14
|
+
servers.each { |details|
|
15
|
+
rstring = (details[:roles] + [ "all", "server-#{details[:name]}" ]).join(' ')
|
16
|
+
f.write("server '#{details[:external_ip]}', roles: %w{#{rstring}}, awsname: '#{details[:name]}'\n")
|
17
|
+
}
|
18
|
+
f.write("set :filter, roles: %w{#{name}}\n")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
if [ -e "/home/<%= user %>/bootstrap.lock" ]; then exit 0; fi
|
3
|
+
DEBIAN_FRONTEND=noninteractive apt-get -y update
|
4
|
+
DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
|
5
|
+
DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
|
6
|
+
DEBIAN_FRONTEND=noninteractive apt-get -y install ruby1.9.3 ruby-dev automake make
|
7
|
+
update-alternatives --set ruby /usr/bin/ruby1.9.1
|
8
|
+
echo "127.0.0.1 <%= host.properties.awsname %>" >> /etc/hosts
|
9
|
+
echo "<%= host.properties.awsname %>" > /etc/hostname
|
10
|
+
hostname "<%= host.properties.awsname %>"
|
11
|
+
cd /usr/src
|
12
|
+
rm -rf rubygems*
|
13
|
+
wget -q http://production.cf.rubygems.org/rubygems/rubygems-<%= rubygems_version %>.tgz
|
14
|
+
tar -zxf rubygems-<%= rubygems_version %>.tgz.tgz
|
15
|
+
cd /usr/src/rubygems-<%= rubygems_version %>
|
16
|
+
ruby setup.rb
|
17
|
+
gem install --no-rdoc --no-ri chef bundler
|
18
|
+
touch /home/<%= user %>/bootstrap.lock
|
19
|
+
echo "Rebooting now, standby..."
|
20
|
+
reboot
|
data/lib/toquen/version.rb
CHANGED
data/lib/toquen.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: toquen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Brian Muller
|
@@ -62,8 +62,11 @@ files:
|
|
62
62
|
- Rakefile
|
63
63
|
- lib/toquen.rb
|
64
64
|
- lib/toquen/aws.rb
|
65
|
+
- lib/toquen/bootstrapper.rb
|
65
66
|
- lib/toquen/capistrano.rb
|
67
|
+
- lib/toquen/local_writer.rb
|
66
68
|
- lib/toquen/templates/deploy.rb
|
69
|
+
- lib/toquen/templates/ubuntu_bootstrap.erb
|
67
70
|
- lib/toquen/version.rb
|
68
71
|
- toquen.gemspec
|
69
72
|
homepage: https://github.com/bmuller/toquen
|
@@ -79,7 +82,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
82
|
requirements:
|
80
83
|
- - ">="
|
81
84
|
- !ruby/object:Gem::Version
|
82
|
-
hash:
|
85
|
+
hash: -1421927206197467486
|
83
86
|
segments:
|
84
87
|
- 0
|
85
88
|
version: "0"
|
@@ -88,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
91
|
requirements:
|
89
92
|
- - ">="
|
90
93
|
- !ruby/object:Gem::Version
|
91
|
-
hash:
|
94
|
+
hash: -1421927206197467486
|
92
95
|
segments:
|
93
96
|
- 0
|
94
97
|
version: "0"
|