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.
- data/Gemfile.lock +1 -1
- data/README.md +35 -18
- data/lib/tango.rb +1 -0
- data/lib/tango/contexts.rb +4 -0
- data/lib/tango/contexts/chain.rb +36 -0
- data/lib/tango/contexts/directory.rb +20 -0
- data/lib/tango/contexts/helpers.rb +19 -0
- data/lib/tango/contexts/umask.rb +19 -0
- data/lib/tango/contexts/user.rb +24 -0
- data/lib/tango/runner.rb +2 -4
- data/lib/tango/version.rb +1 -1
- data/spec/contexts/chain_spec.rb +78 -0
- data/spec/contexts/directory_spec.rb +37 -0
- data/spec/contexts/umask_spec.rb +33 -0
- metadata +17 -8
- data/lib/tango/as_user.rb +0 -17
- data/lib/tango/working_directory.rb +0 -15
- data/spec/working_directory_spec.rb +0 -57
data/Gemfile.lock
CHANGED
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
|
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
|
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
|
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
|
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
|
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
|
101
|
-
|
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
|
-
###
|
123
|
+
### Changing the umask
|
107
124
|
|
108
|
-
step
|
109
|
-
|
110
|
-
|
125
|
+
step :install do
|
126
|
+
with_umask 0077 do
|
127
|
+
shell "make install"
|
111
128
|
end
|
112
129
|
end
|
113
130
|
|
114
|
-
###
|
131
|
+
### Running As Another User
|
115
132
|
|
116
|
-
step
|
117
|
-
|
118
|
-
|
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
|
|
data/lib/tango.rb
CHANGED
@@ -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,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
|
data/lib/tango/runner.rb
CHANGED
@@ -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|
|
data/lib/tango/version.rb
CHANGED
@@ -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:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
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-
|
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
|
data/lib/tango/as_user.rb
DELETED
@@ -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,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
|
-
|