teleport 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -6,7 +6,7 @@ Teleport strives to be **idempotent** - you can run it repeatedly without changi
6
6
 
7
7
  Teleport is great for managing a small number of hosted machines, either dedicated or in the cloud. Due to it's opinionated nature and limited scope you may find that it works better for you than other, more complicated tools.
8
8
 
9
- At the moment Teleport supports **Ubuntu 10.04/10.10/11.04 with Ruby 1.8.7, 1.9.2, or [REE](http://www.rubyenterpriseedition.com/)**.
9
+ At the moment Teleport supports **Ubuntu 10.04/10.10/11.04 with Ruby 1.8.7, 1.9.2, 1.9.3, or [REE](http://www.rubyenterpriseedition.com/)**.
10
10
 
11
11
  ## Getting Started
12
12
 
@@ -27,7 +27,7 @@ At the moment Teleport supports **Ubuntu 10.04/10.10/11.04 with Ruby 1.8.7, 1.9.
27
27
 
28
28
  ``` ruby
29
29
  user "admin"
30
- ruby "1.9.2"
30
+ ruby "1.9.3"
31
31
  apt "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen", :key => "7F0CAB10"
32
32
  role :app, :packages => [:memcached]
33
33
  role :db, :packages => [:mongodb-10gen]
@@ -60,3 +60,4 @@ Teleport will ssh to the machine and set it up per your instructions.
60
60
  Full docs are in the wiki:
61
61
 
62
62
  https://github.com/gurgeous/teleport/wiki
63
+
@@ -3,13 +3,14 @@ module Teleport
3
3
  class Config
4
4
  RUBIES = ["1.9.3", "1.9.2", "REE", "1.8.7"]
5
5
 
6
- attr_accessor :user, :ruby, :ssh_options, :roles, :servers, :apt, :packages, :callbacks, :dsl
7
-
6
+ attr_accessor :user, :ruby, :ssh_options, :roles, :servers, :apt, :packages, :recipes, :callbacks, :dsl
7
+
8
8
  def initialize(file = "Telfile")
9
9
  @roles = []
10
10
  @servers = []
11
11
  @apt = []
12
12
  @packages = []
13
+ @recipes = []
13
14
  @callbacks = { }
14
15
 
15
16
  @dsl = DSL.new(self)
@@ -26,7 +27,7 @@ module Teleport
26
27
  end
27
28
 
28
29
  def server(n)
29
- @servers.find { |i| i.name == n.to_s }
30
+ @servers.find { |i| i.name == n.to_s }
30
31
  end
31
32
 
32
33
  def sanity_check_gemfiles
@@ -42,34 +43,50 @@ module Teleport
42
43
 
43
44
  # The model for role in the Telfile.
44
45
  class Role
45
- attr_reader :name, :options, :packages
46
-
46
+ attr_reader :name, :options, :packages, :recipes
47
+
47
48
  def initialize(name, options)
48
49
  raise "role name must be a sym" if !name.is_a?(Symbol)
49
50
  raise "role options must be a hash" if !options.is_a?(Hash)
50
-
51
- @name, @options, @packages = name, options, []
51
+
52
+ @name, @options, @packages, @recipes = name, options, [], []
53
+
54
+ # Packages
52
55
  if p = @options.delete(:packages)
53
56
  raise "role :packages must be an array" if !p.is_a?(Array)
54
57
  @packages = p
55
58
  end
59
+
60
+ # Recipes
61
+ if r = @options.delete(:recipes)
62
+ raise "server :recipes must be an array" if !r.is_a?(Array)
63
+ @recipes = r
64
+ end
56
65
  end
57
66
  end
58
67
 
59
68
  # The model for server in the Telfile.
60
69
  class Server
61
- attr_reader :name, :options, :packages
62
-
70
+ attr_reader :name, :options, :packages, :recipes
71
+
63
72
  def initialize(name, options)
64
73
  raise "server name must be a string" if !name.is_a?(String)
65
74
  raise "server options must be a hash" if !options.is_a?(Hash)
66
- raise "server :role must be a sym" if !options[:role].is_a?(Symbol)
67
-
68
- @name, @options, @packages = name, options, []
75
+ raise "server :role must be a sym" if options[:role] && !options[:role].is_a?(Symbol)
76
+
77
+ @name, @options, @packages, @recipes = name, options, [], []
78
+
79
+ # Packages
69
80
  if p = @options.delete(:packages)
70
81
  raise "server :packages must be an array" if !p.is_a?(Array)
71
82
  @packages = p
72
83
  end
84
+
85
+ # Recipes
86
+ if r = @options.delete(:recipes)
87
+ raise "server :recipes must be an array" if !r.is_a?(Array)
88
+ @recipes = r
89
+ end
73
90
  end
74
91
  end
75
92
 
@@ -96,20 +113,20 @@ module Teleport
96
113
 
97
114
  def ruby(v)
98
115
  raise "ruby called twice" if @config.ruby
99
- raise "ruby must be a string" if !v.is_a?(String)
116
+ raise "ruby must be a string" if !v.is_a?(String)
100
117
  raise "don't recognize ruby #{v.inspect}." if !Config::RUBIES.include?(v)
101
118
  @config.ruby = v
102
119
  end
103
-
120
+
104
121
  def user(v)
105
122
  raise "user called twice" if @config.user
106
- raise "user must be a string" if !v.is_a?(String)
123
+ raise "user must be a string" if !v.is_a?(String)
107
124
  @config.user = v
108
125
  end
109
126
 
110
127
  def ssh_options(v)
111
128
  raise "ssh_options called twice" if @config.ssh_options
112
- raise "ssh_options must be an Array" if !v.is_a?(Array)
129
+ raise "ssh_options must be an Array" if !v.is_a?(Array)
113
130
  @config.ssh_options = v
114
131
  end
115
132
 
@@ -131,7 +148,11 @@ module Teleport
131
148
  @config.packages += list.flatten
132
149
  end
133
150
 
134
- %w(install user packages gemfiles files).each do |op|
151
+ def recipes(*list)
152
+ @config.recipes += list.flatten
153
+ end
154
+
155
+ %w(install user packages gemfiles files recipes).each do |op|
135
156
  %w(before after).each do |before_after|
136
157
  callback = "#{before_after}_#{op}".to_sym
137
158
  define_method(callback) do |&block|
@@ -1,10 +1,10 @@
1
1
  module Teleport
2
2
  # Class that performs the install on the target machine.
3
3
  class Install
4
- include Constants
4
+ include Constants
5
5
  include Util
6
- include Mirror
7
-
6
+ include Mirror
7
+
8
8
  def initialize(config)
9
9
  @config = config
10
10
  run_verbose!
@@ -16,10 +16,10 @@ module Teleport
16
16
  Config::DSL.const_set("ROLE", @role && @role.name)
17
17
 
18
18
  # add mixins
19
- @config.dsl.extend(Mirror)
19
+ @config.dsl.extend(Mirror)
20
20
  @config.dsl.extend(Util)
21
21
  @config.dsl.run_verbose!
22
-
22
+
23
23
  _with_callback(:install) do
24
24
  _gems
25
25
  _hostname
@@ -36,6 +36,9 @@ module Teleport
36
36
  _with_callback(:files) do
37
37
  _files
38
38
  end
39
+ _with_callback(:recipes) do
40
+ _recipes
41
+ end
39
42
  end
40
43
  end
41
44
 
@@ -80,6 +83,28 @@ module Teleport
80
83
  gem_if_necessary("bundler")
81
84
  end
82
85
 
86
+ def _recipes
87
+ list = @config.recipes
88
+ list += @role.recipes if @role
89
+ list += @server.recipes if @server
90
+
91
+ banner "Recipes..."
92
+ list.each do |recipe|
93
+ path = "#{DATA}/recipes/#{recipe}"
94
+ if File.exists?(path)
95
+ banner "#{recipe}..."
96
+ # eval ruby files instead of running them
97
+ if path =~ /\.rb$/
98
+ eval(File.read(path), nil, path)
99
+ else
100
+ run path
101
+ end
102
+ else
103
+ fatal "Recipe '#{recipe}' does not exist inside recipes/"
104
+ end
105
+ end
106
+ end
107
+
83
108
  def _hostname
84
109
  banner "Hostname..."
85
110
 
@@ -87,10 +112,10 @@ module Teleport
87
112
  return if @host =~ /^\d+(\.\d+){3}$/
88
113
  # ipv6?
89
114
  return if @host =~ /:/
90
-
115
+
91
116
  old_hostname = `hostname`.strip
92
117
  return if old_hostname == @host
93
-
118
+
94
119
  puts "setting hostname to #{@host} (it was #{old_hostname})..."
95
120
  File.open("/etc/hostname", "w") do |f|
96
121
  f.write @host
@@ -123,7 +148,7 @@ module Teleport
123
148
 
124
149
  def _create_user
125
150
  user = @config.user
126
-
151
+
127
152
  banner "Creating #{user} account..."
128
153
  # create the account
129
154
  if !File.directory?("/home/#{user}")
@@ -157,7 +182,7 @@ EOF
157
182
  banner "Apt..."
158
183
 
159
184
  dirty = false
160
-
185
+
161
186
  # keys
162
187
  keys = @config.apt.map { |i| i.options[:key] }.compact
163
188
  keys.each do |i|
@@ -214,7 +239,7 @@ EOF
214
239
  end
215
240
 
216
241
  protected
217
-
242
+
218
243
  def _with_callback(op, &block)
219
244
  if before = @config.callbacks["before_#{op}".to_sym]
220
245
  before.call
@@ -241,7 +266,7 @@ EOF
241
266
  end
242
267
 
243
268
  def _etc_hosts_regex(host)
244
- /^([^#]+[ \t])#{Regexp.escape(host)}([ \t]|$)/
269
+ /^([^#]+[ \t])#{Regexp.escape(host)}([ \t]|$)/
245
270
  end
246
271
  end
247
272
  end
data/lib/teleport/main.rb CHANGED
@@ -77,6 +77,7 @@ module Teleport
77
77
  copy = []
78
78
  copy << "Telfile"
79
79
  copy += Dir["files*"]
80
+ copy << "recipes" if File.exists?("recipes")
80
81
  copy.sort.each { |i| run("cp", ["-r", i, DATA]) }
81
82
  # config.sh
82
83
  File.open("#{DIR}/config", "w") do |f|
@@ -110,7 +111,7 @@ module Teleport
110
111
  "cd /tmp",
111
112
  "(sudo -n echo gub > /dev/null 2> /dev/null || (echo `whoami` could not sudo. && exit 1))",
112
113
  "sudo rm -rf #{DIR}",
113
- "sudo tar xfpz #{TAR}",
114
+ "sudo tar xmfpz #{TAR}",
114
115
  "sudo #{DIR}/gem/teleport/run.sh"
115
116
  ]
116
117
  banner "ssh to #{@options[:host]} and run..."
@@ -1,4 +1,4 @@
1
1
  module Teleport
2
2
  # Gem version
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.3"
4
4
  end
@@ -11,8 +11,8 @@ user "gub"
11
11
  ruby "1.8.7"
12
12
  ssh_options ["-o", "User=ubuntu", "-o", "StrictHostKeyChecking=no", "-o", "IdentityFile=#{ENV["TELEPORT_SSH_KEY"]}"]
13
13
 
14
- role :master, :packages => %w(nginx)
15
- server "#{$ec2_ip_address}", :role => :master, :packages => %w(strace)
14
+ role :master, :packages => %w(nginx), :recipes => %w(ruby.rb)
15
+ server "#{$ec2_ip_address}", :role => :master, :packages => %w(strace), :recipes => %w(some_command)
16
16
  packages %w(atop)
17
17
 
18
18
  before_install do
@@ -30,16 +30,28 @@ after_gemfiles do
30
30
  Util.run "gem list"
31
31
  end
32
32
 
33
+ after_recipes do
34
+ puts "AFTER_RECIPES"
35
+ end
36
+
33
37
  after_install do
34
38
  puts "AFTER_INSTALL"
35
39
  run "touch /tmp/gub.txt"
36
40
  end
41
+
37
42
  EOF
38
43
  end
39
44
 
40
45
  # Roles. This is clunky, unfortunately.
41
- role(nil, "test.txt.erb" => "<%= 1+2 %>", "Gemfile" => "source 'http://rubygems.org'\ngem 'trollop'", "Gemfile.lock" => "GEM\n remote: http://rubygems.org/\n specs:\n trollop (1.16.2)\n\nPLATFORMS\n ruby\n\nDEPENDENCIES\n trollop")
42
- role("master", "Gemfile" => "source 'http://rubygems.org'\ngem 'awesome_print'", "Gemfile.lock" => "GEM\n remote: http://rubygems.org/\n specs:\n awesome_print (0.4.0)\n\nPLATFORMS\n ruby\n\nDEPENDENCIES\n awesome_print")
46
+
47
+ # amd: commenting the Gemfiles because they are too slow. revisit for bundler 1.1?
48
+ # role(nil, "test.txt.erb" => "<%= 1+2 %>", "Gemfile" => "source 'http://rubygems.org'\ngem 'trollop'", "Gemfile.lock" => "GEM\n remote: http://rubygems.org/\n specs:\n trollop (1.16.2)\n\nPLATFORMS\n ruby\n\nDEPENDENCIES\n trollop")
49
+ # role("master", "Gemfile" => "source 'http://rubygems.org'\ngem 'awesome_print'", "Gemfile.lock" => "GEM\n remote: http://rubygems.org/\n specs:\n awesome_print (0.4.0)\n\nPLATFORMS\n ruby\n\nDEPENDENCIES\n awesome_print")
50
+ role(nil, "test.txt.erb" => "<%= 1+2 %>")
51
+
52
+ # Recipes
53
+ recipe("ruby.rb", "Util.run 'echo ruby.rb is running'")
54
+ recipe("some_command", "#!/bin/bash\necho some_command is running")
43
55
 
44
56
  it "installs properly" do
45
57
  ARGV.clear
@@ -33,5 +33,18 @@ module Support
33
33
  end
34
34
  end
35
35
  end
36
+
37
+ def recipe(name, content)
38
+ before(:all) do
39
+ path = "recipes"
40
+ `mkdir -p #{path}`
41
+ Dir.chdir(path) do
42
+ File.open(name, "w") { |f| f.write(content) }
43
+ if name !~ /\.rb/
44
+ File.chmod 0755, name
45
+ end
46
+ end
47
+ end
48
+ end
36
49
  end
37
50
  end
@@ -8,7 +8,7 @@ describe Teleport::Config do
8
8
  Teleport::Config.new
9
9
  end
10
10
  it "defaults to the current username" do
11
- config.user.should == `whoami`.strip
11
+ config.user.should == `whoami`.strip
12
12
  end
13
13
  it "defaults to the first vm in RUBIES" do
14
14
  config.ruby.should == Teleport::Config::RUBIES.first
@@ -21,11 +21,12 @@ describe Teleport::Config do
21
21
  user "somebody"
22
22
  ruby "1.8.7"
23
23
 
24
- role :master, :packages => %w(nginx)
24
+ role :master, :packages => %w(nginx), :recipes => %w(master.rb)
25
25
  role :slave, :packages => %w(memcached)
26
26
  server "one", :role => :master, :packages => %w(strace)
27
- server "two", :role => :slave, :packages => %w(telnet)
27
+ server "two", :role => :slave, :packages => %w(telnet), :recipes => %w(two.rb)
28
28
  packages %w(atop)
29
+ recipes %w(global.rb)
29
30
  apt "blah blah blah", :key => "123"
30
31
 
31
32
  before_install do
@@ -37,28 +38,38 @@ after_install do
37
38
  end
38
39
  EOF
39
40
  end
40
-
41
+
41
42
  let(:config) do
42
43
  Teleport::Config.new
43
44
  end
44
45
  it "has the master role" do
45
46
  config.role(:master).name.should == :master
46
47
  config.role(:master).packages.should == %w(nginx)
48
+ config.role(:master).recipes.should == %w(master.rb)
47
49
  end
48
50
  it "has server one" do
49
51
  config.server("one").name.should == "one"
50
52
  config.server("one").packages.should == %w(strace)
53
+ config.server("one").recipes.should == []
54
+ end
55
+ it "has server two" do
56
+ config.server("two").name.should == "two"
57
+ config.server("two").packages.should == %w(telnet)
58
+ config.server("two").recipes.should == %w(two.rb)
51
59
  end
52
60
  it "has default packages" do
53
61
  config.packages.should == %w(atop)
54
62
  end
63
+ it "has default recipes" do
64
+ config.recipes.should == %w(global.rb)
65
+ end
55
66
  it "has callbacks" do
56
67
  config.callbacks[:before_install].should_not == nil
57
- config.callbacks[:after_install].should_not == nil
68
+ config.callbacks[:after_install].should_not == nil
58
69
  end
59
70
  it "has an apt line" do
60
71
  config.apt.first.line.should == "blah blah blah"
61
- config.apt.first.options[:key].should == "123"
72
+ config.apt.first.options[:key].should == "123"
62
73
  end
63
74
  end
64
75
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teleport
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 2
10
- version: 1.0.2
9
+ - 3
10
+ version: 1.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Adam Doppelt
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-02 00:00:00 -07:00
18
+ date: 2011-11-03 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency