tango 0.0.9 → 0.1.0

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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tango (0.0.9)
4
+ tango (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -31,10 +31,8 @@ Example Runner
31
31
  shell("dpkg-query", "--status", package, :echo => false).output !~ /not.installed|deinstall/
32
32
  end
33
33
 
34
- step "install" do |package|
34
+ step :install do |package|
35
35
  met? { installed?(package) }
36
- # Need to figure out how to make this non-interactive. See:
37
- # http://ubuntuforums.org/showthread.php?t=1218525
38
36
  meet { shell("apt-get", "install", "-y", package) }
39
37
  end
40
38
  end
@@ -44,7 +42,7 @@ Example Runner
44
42
  shell("gem", "query", "--installed", "--name-matches", gem, :echo => false).output =~ /true/
45
43
  end
46
44
 
47
- step "install" do |gem|
45
+ step :install do |gem|
48
46
  met? { installed?(gem) }
49
47
  meet { shell("gem", "install", gem) }
50
48
  end
@@ -56,7 +54,7 @@ Example Runner
56
54
  @gem = GemInstaller.new
57
55
  end
58
56
 
59
- step "install" do
57
+ step :install do
60
58
  @apt.install "build-essential"
61
59
 
62
60
  @apt.install "mysql-server"
@@ -71,23 +69,25 @@ Example Runner
71
69
  Running the Example
72
70
  -------------------
73
71
 
74
- tango example_installer.rb ExampleInstaller.install
72
+ sudo tango example_installer.rb ExampleInstaller.install
75
73
 
76
74
  Useful Helper Methods
77
75
  ---------------------
78
76
 
79
77
  ### Running Shell Commands
80
78
 
81
- step "install something" do
79
+ step :install_something do
82
80
  result = shell("apt-get", "install", "something")
83
81
  if result.succeeded?
84
82
  write("/tmp/something-install.log", result.output)
85
83
  end
86
84
  end
87
85
 
86
+ Use shell! to raise an exception if the command exits with non-zero status.
87
+
88
88
  ### Writing Config Files
89
89
 
90
- step "configure foo" do
90
+ step :configure_foo do
91
91
  @log_directory = "/var/log/foo.log"
92
92
  write "/etc/foo.conf", <<-EOF
93
93
  # Config file for foo
@@ -95,27 +95,44 @@ Useful Helper Methods
95
95
  end
96
96
  end
97
97
 
98
+ ### Fetching a Remote URL
99
+
100
+ step :install do
101
+ cd "/tmp" do
102
+ fetch "http://example.com/something.tar.gz"
103
+ end
104
+ end
105
+
106
+ Chainable Helper Methods
107
+ ------------------------
108
+
109
+ You can use these together like this:
110
+
111
+ in_directory("/tmp").with_umask(0022) do
112
+ ...
113
+ end
114
+
98
115
  ### Changing the Working Directory
99
116
 
100
- step "migrate" do
101
- cd "/rails_apps/blog" do
117
+ step :migrate do
118
+ in_directory "/rails_apps/blog" do
102
119
  shell "rake db:migrate"
103
120
  end
104
121
  end
105
122
 
106
- ### Running As Another User
123
+ ### Changing the umask
107
124
 
108
- step "..." do
109
- as "fred" do
110
- FileUtils.touch("/home/fred/fred_woz_ere")
125
+ step :install do
126
+ with_umask 0077 do
127
+ shell "make install"
111
128
  end
112
129
  end
113
130
 
114
- ### Fetching a Remote URL
131
+ ### Running As Another User
115
132
 
116
- step "..." do
117
- cd "/tmp" do
118
- fetch "http://example.com/something.tar.gz"
133
+ step :install do
134
+ as_user "fred" do
135
+ FileUtils.touch("/home/fred/fred_woz_ere")
119
136
  end
120
137
  end
121
138
 
@@ -1,2 +1,3 @@
1
+ require 'tango/contexts'
1
2
  require 'tango/logger'
2
3
  require 'tango/runner'
@@ -0,0 +1,4 @@
1
+ require 'tango/contexts/chain'
2
+ require 'tango/contexts/directory'
3
+ require 'tango/contexts/helpers'
4
+ require 'tango/contexts/umask'
@@ -0,0 +1,36 @@
1
+ require 'tango/contexts/helpers'
2
+
3
+ module Tango
4
+ module Contexts
5
+ class Chain
6
+
7
+ include Helpers
8
+
9
+ def initialize
10
+ @contexts = []
11
+ end
12
+
13
+ def in_context(context, &block)
14
+ @contexts << context
15
+ if block_given?
16
+ call_in_contexts(&block)
17
+ else
18
+ self
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def call_in_contexts
25
+ @contexts.each {|context| context.enter }
26
+ begin
27
+ yield
28
+ ensure
29
+ @contexts.reverse.each {|context| context.leave }
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,20 @@
1
+ module Tango
2
+ module Contexts
3
+ class Directory
4
+
5
+ def initialize(directory)
6
+ @directory = directory
7
+ end
8
+
9
+ def enter
10
+ @old_directory = Dir.getwd
11
+ Dir.chdir(@directory)
12
+ end
13
+
14
+ def leave
15
+ Dir.chdir(@old_directory)
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Tango
2
+ module Contexts
3
+ module Helpers
4
+
5
+ def in_context(context, &block)
6
+ Chain.new.in_context(context, &block)
7
+ end
8
+
9
+ def in_directory(directory, &block)
10
+ in_context(Directory.new(directory), &block)
11
+ end
12
+
13
+ def with_umask(umask, &block)
14
+ in_context(Umask.new(umask), &block)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Tango
2
+ module Contexts
3
+ class Umask
4
+
5
+ def initialize(umask)
6
+ @umask = umask
7
+ end
8
+
9
+ def enter
10
+ @old_umask = File.umask(@umask)
11
+ end
12
+
13
+ def leave
14
+ File.umask(@old_umask)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ module Tango
2
+ module Contexts
3
+ class User
4
+
5
+ def initialize(username)
6
+ @username = username
7
+ end
8
+
9
+ def enter
10
+ @uid, @gid = Process.euid, Process.egid
11
+ Process::Sys.seteuid(0) if @uid != 0
12
+ info = Etc.getpwnam(@username)
13
+ Process::Sys.setegid(info.gid)
14
+ Process::Sys.seteuid(info.uid)
15
+ end
16
+
17
+ def leave
18
+ Process::Sys.seteuid(@uid)
19
+ Process::Sys.setegid(@gid)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -1,20 +1,18 @@
1
- require 'tango/as_user'
2
1
  require 'tango/config_files'
2
+ require 'tango/contexts/helpers'
3
3
  require 'tango/delegate'
4
4
  require 'tango/fetch'
5
5
  require 'tango/met_and_meet'
6
6
  require 'tango/shell'
7
- require 'tango/working_directory'
8
7
 
9
8
  module Tango
10
9
  class Runner
11
- include AsUser
12
10
  include ConfigFiles
11
+ include Contexts::Helpers
13
12
  include Delegate
14
13
  include Fetch
15
14
  include MetAndMeet
16
15
  include Shell
17
- include WorkingDirectory
18
16
 
19
17
  def self.step(step_name, &block)
20
18
  define_method(step_name) do |*args|
@@ -1,3 +1,3 @@
1
1
  module Tango
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,78 @@
1
+ require 'tango'
2
+
3
+ module Tango::Contexts
4
+ describe Chain do
5
+
6
+ before do
7
+ @context_class = Class.new do
8
+ def in_context?
9
+ @in_context
10
+ end
11
+
12
+ def initialize
13
+ @in_context = false
14
+ end
15
+
16
+ def enter
17
+ @in_context = true
18
+ end
19
+
20
+ def leave
21
+ @in_context = false
22
+ end
23
+ end
24
+
25
+ @context = @context_class.new
26
+ end
27
+
28
+ it "should run a block" do
29
+ block_run = false
30
+ Chain.new.in_context(@context) { block_run = true }
31
+ block_run.should be_true
32
+ end
33
+
34
+ it "should return the return value of the block" do
35
+ result = Chain.new.in_context(@context) { "I woz ere." }
36
+ result.should == "I woz ere."
37
+ end
38
+
39
+ it "should run the context's enter method before the block" do
40
+ Chain.new.in_context(@context) do
41
+ @context.should be_in_context
42
+ end
43
+ end
44
+
45
+ it "should run the context's leave method after leaving the block" do
46
+ Chain.new.in_context(@context) { }
47
+ @context.should_not be_in_context
48
+ end
49
+
50
+ it "should run the context's leave method on an exception" do
51
+ expect {
52
+ Chain.new.in_context(@context) { raise "Uh oh" }
53
+ }.should raise_error("Uh oh")
54
+ @context.should_not be_in_context
55
+ end
56
+
57
+ describe "when chaining contexts" do
58
+ before do
59
+ @a = @context_class.new
60
+ @b = @context_class.new
61
+ end
62
+
63
+ it "should run the enter method of each context" do
64
+ Chain.new.in_context(@a).in_context(@b) do
65
+ @a.should be_in_context
66
+ @b.should be_in_context
67
+ end
68
+ end
69
+
70
+ it "should run the leave method of each context" do
71
+ Chain.new.in_context(@a).in_context(@b) { }
72
+ @a.should_not be_in_context
73
+ @b.should_not be_in_context
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,37 @@
1
+ require 'tango'
2
+
3
+ module Tango::Contexts
4
+ describe Directory do
5
+
6
+ before do
7
+ stub_class = Class.new do
8
+ include Helpers
9
+ end
10
+ @stub = stub_class.new
11
+
12
+ # Make doubly sure we reset the working directory after each test.
13
+ @original_directory = Dir.getwd
14
+ end
15
+
16
+ after do
17
+ Dir.chdir(@original_directory)
18
+ end
19
+
20
+ it "should change the working directory" do
21
+ directory = Dir.getwd + "/lib"
22
+ @stub.in_directory(directory) do
23
+ Dir.getwd.should == directory
24
+ end
25
+ end
26
+
27
+ it "should restore the original working directory" do
28
+ old_directory = Dir.getwd
29
+ directory = Dir.getwd + "/lib"
30
+ @stub.in_directory(directory) { }
31
+ Dir.getwd.should == old_directory
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+
@@ -0,0 +1,33 @@
1
+ require 'tango'
2
+
3
+ module Tango::Contexts
4
+ describe Umask do
5
+
6
+ before do
7
+ stub_class = Class.new do
8
+ include Helpers
9
+ end
10
+ @stub = stub_class.new
11
+
12
+ # Make double sure we reset the umask after each test.
13
+ @original_umask = File.umask
14
+ end
15
+
16
+ after do
17
+ File.umask(@original_umask)
18
+ end
19
+
20
+ it "should change the umask" do
21
+ @stub.with_umask(0777) do
22
+ File.umask.should == 0777
23
+ end
24
+ end
25
+
26
+ it "should restore the original umask" do
27
+ old_umask = File.umask
28
+ @stub.with_umask(0777) { }
29
+ File.umask.should == old_umask
30
+ end
31
+
32
+ end
33
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tango
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 9
10
- version: 0.0.9
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Pete Yandell
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-13 00:00:00 +10:00
18
+ date: 2011-04-14 00:00:00 +10:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -51,8 +51,13 @@ files:
51
51
  - Rakefile
52
52
  - bin/tango
53
53
  - lib/tango.rb
54
- - lib/tango/as_user.rb
55
54
  - lib/tango/config_files.rb
55
+ - lib/tango/contexts.rb
56
+ - lib/tango/contexts/chain.rb
57
+ - lib/tango/contexts/directory.rb
58
+ - lib/tango/contexts/helpers.rb
59
+ - lib/tango/contexts/umask.rb
60
+ - lib/tango/contexts/user.rb
56
61
  - lib/tango/delegate.rb
57
62
  - lib/tango/fetch.rb
58
63
  - lib/tango/logger.rb
@@ -60,14 +65,16 @@ files:
60
65
  - lib/tango/runner.rb
61
66
  - lib/tango/shell.rb
62
67
  - lib/tango/version.rb
63
- - lib/tango/working_directory.rb
64
68
  - spec/config_files_spec.rb
69
+ - spec/contexts/chain_spec.rb
70
+ - spec/contexts/directory_spec.rb
71
+ - spec/contexts/umask_spec.rb
65
72
  - spec/logger_spec.rb
66
73
  - spec/met_and_meet_spec.rb
67
74
  - spec/runner_spec.rb
68
75
  - spec/shell_spec.rb
69
- - spec/working_directory_spec.rb
70
76
  - tango.gemspec
77
+ - tmp/.gitignore
71
78
  has_rdoc: true
72
79
  homepage: ""
73
80
  licenses: []
@@ -104,8 +111,10 @@ specification_version: 3
104
111
  summary: Experiment in deployment tools.
105
112
  test_files:
106
113
  - spec/config_files_spec.rb
114
+ - spec/contexts/chain_spec.rb
115
+ - spec/contexts/directory_spec.rb
116
+ - spec/contexts/umask_spec.rb
107
117
  - spec/logger_spec.rb
108
118
  - spec/met_and_meet_spec.rb
109
119
  - spec/runner_spec.rb
110
120
  - spec/shell_spec.rb
111
- - spec/working_directory_spec.rb
@@ -1,17 +0,0 @@
1
- module Tango
2
- module AsUser
3
-
4
- def as(username)
5
- info = Etc.getpwent(username)
6
- uid, gid = Process.euid, Process.egid
7
- Process::Sys.seteuid(0) if uid != 0
8
- Process::Sys.setegid(info.gid)
9
- Process::Sys.seteuid(info.uid)
10
- yield
11
- ensure
12
- Process::Sys.seteuid(uid)
13
- Process::Sys.setegid(gid)
14
- end
15
-
16
- end
17
- end
@@ -1,15 +0,0 @@
1
- module Tango
2
- module WorkingDirectory
3
-
4
- def cd(directory)
5
- old_directory = Dir.getwd
6
- begin
7
- Dir.chdir(directory)
8
- yield
9
- ensure
10
- Dir.chdir(old_directory)
11
- end
12
- end
13
-
14
- end
15
- end
@@ -1,57 +0,0 @@
1
- require 'tango'
2
-
3
- module Tango
4
- describe WorkingDirectory do
5
-
6
- before do
7
- stub_class = Class.new do
8
- include WorkingDirectory
9
- end
10
- @stub = stub_class.new
11
-
12
- # Make doubly sure we reset the working directory after each test.
13
- @original_directory = Dir.getwd
14
- end
15
-
16
- after do
17
- Dir.chdir(@original_directory)
18
- end
19
-
20
- it "should run a block" do
21
- block_run = false
22
- @stub.cd("/tmp") { block_run = true }
23
- block_run.should be_true
24
- end
25
-
26
- it "should return the return value of the block" do
27
- result = @stub.cd("/tmp") { "I woz ere." }
28
- result.should == "I woz ere."
29
- end
30
-
31
- it "should change directory" do
32
- directory = Dir.getwd + "/lib"
33
- @stub.cd(directory) do
34
- Dir.getwd.should == directory
35
- end
36
- end
37
-
38
- it "should restore the original working directory" do
39
- old_directory = Dir.getwd
40
- directory = Dir.getwd + "/lib"
41
- @stub.cd(directory) { }
42
- Dir.getwd.should == old_directory
43
- end
44
-
45
- it "should restore the original directory after an exception" do
46
- old_directory = Dir.getwd
47
- directory = Dir.getwd + "/lib"
48
- expect {
49
- @stub.cd(directory) { raise "Uh oh!" }
50
- }.should raise_error
51
- Dir.getwd.should == old_directory
52
- end
53
-
54
- end
55
- end
56
-
57
-