tango 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ .DS_Store
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tango (0.0.3)
4
+ tango (0.0.4)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ Credit Where It's Due
2
+ ---------------------
3
+
4
+ This is a re-invention of Ben Hoskings's excellent
5
+ [Babushka](https://github.com/benhoskings/babushka).
6
+
7
+ There are a bunch of things I love about Babushka, and a bunch of other things
8
+ that really don't fit with the way we want to use it at
9
+ [Envato](http://envato.com/). Tango is an experiment in changing around a few
10
+ of Babushka's fundamentals to try to find a better fit.
11
+
12
+
13
+ Example
14
+ -------
15
+
16
+ class Homebrew < Tango::Namespace
17
+ def installed?(formula)
18
+ `brew info #{formula}` !~ /Not installed/
19
+ end
20
+
21
+ step "bootstrap" do
22
+ met? { system "brew info" }
23
+ meet { system %{ruby -e "$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)"} }
24
+ end
25
+
26
+ step "install" do |formula|
27
+ met? { installed?(formula) }
28
+ meet { system "brew install #{formula}" }
29
+ end
30
+ end
31
+
32
+ class MyNamespace < Tango::Namespace
33
+ step "install" do
34
+ Homebrew.run "bootstrap"
35
+ Homebrew.run "install", "git"
36
+ Homebrew.run "install", "mysql"
37
+ run "install mtr"
38
+ end
39
+
40
+ step "install mtr" do
41
+ met? { Homebrew.installed?("mtr") }
42
+ meet { system "brew install --no-gtk mtr" }
43
+ end
44
+ end
45
+
data/bin/tango CHANGED
@@ -3,10 +3,8 @@
3
3
  $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib")
4
4
  require 'tango'
5
5
 
6
- def dance(name, &block)
7
- Tango::DanceCard.instance.dance(name, &block)
8
- end
9
-
10
6
  load ARGV[0]
11
7
 
12
- Tango::DanceCard.instance.run ARGV[1]
8
+ namespace_name, step_name = ARGV[1].split(".")
9
+
10
+ Object.const_get(namespace_name).run(step_name)
data/lib/tango.rb CHANGED
@@ -1,5 +1,4 @@
1
- require 'tango/dance'
2
- require 'tango/dance_card'
3
- require 'tango/errors'
1
+ require 'tango/as_user'
4
2
  require 'tango/logger'
5
- require 'tango/step_runner'
3
+ require 'tango/met_and_meet'
4
+ require 'tango/namespace'
@@ -0,0 +1,17 @@
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
data/lib/tango/logger.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  module Tango
2
2
  class Logger
3
-
3
+ def self.instance
4
+ @logger ||= Logger.new
5
+ end
6
+
4
7
  def initialize(io = STDERR)
5
8
  @io = io
6
9
  @depth = 0
@@ -0,0 +1,28 @@
1
+ module Tango
2
+ class CouldNotMeetError < RuntimeError; end
3
+ class MeetWithoutMetError < RuntimeError; end
4
+
5
+ module MetAndMeet
6
+
7
+ def met?(&met_block)
8
+ @met_block = met_block
9
+ end
10
+
11
+ def meet(&meet_block)
12
+ raise MeetWithoutMetError if @met_block.nil?
13
+
14
+ if instance_eval(&@met_block)
15
+ log "already met."
16
+ else
17
+ log "not already met."
18
+ instance_eval(&meet_block)
19
+ if instance_eval(&@met_block)
20
+ log "met."
21
+ else
22
+ raise CouldNotMeetError
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ require 'tango/as_user'
2
+ require 'tango/met_and_meet'
3
+
4
+ module Tango
5
+ class Namespace
6
+ include AsUser
7
+ include MetAndMeet
8
+
9
+ def self.step(step_name, &block)
10
+ define_method(step_name, &block)
11
+ end
12
+
13
+ def self.run(step_name, *args)
14
+ description = "#{name}.#{step_name}"
15
+ description << "(" + args.map {|arg| arg.inspect }.join(", ") + ")" unless args.empty?
16
+
17
+ logger.enter(description)
18
+ new.send(step_name, *args)
19
+ logger.leave(description)
20
+ end
21
+
22
+ def run(step_name, *args)
23
+ self.class.run(step_name, *args)
24
+ end
25
+
26
+ def log(message)
27
+ self.class.logger.log(message)
28
+ end
29
+
30
+ def self.method_missing(method, *args)
31
+ new.send(method, *args)
32
+ end
33
+
34
+ private
35
+
36
+ def self.logger
37
+ Logger.instance
38
+ end
39
+
40
+ end
41
+ end
data/lib/tango/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tango
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,74 @@
1
+ require 'tango'
2
+
3
+ module Tango
4
+ describe MetAndMeet do
5
+
6
+ before do
7
+ @stub = Class.new do
8
+ include MetAndMeet
9
+
10
+ def log(message); end
11
+ end
12
+ end
13
+
14
+ it "should check the met?, run the meet, then check the met? again" do
15
+ met_block_calls = 0
16
+ meet_block_calls = 0
17
+
18
+ @stub.new.instance_eval do
19
+ met? do
20
+ met_block_calls += 1
21
+ meet_block_calls > 0
22
+ end
23
+ meet { meet_block_calls += 1 }
24
+ end
25
+
26
+ met_block_calls.should == 2
27
+ meet_block_calls.should == 1
28
+ end
29
+
30
+ it "should not run the meet if the met? succeeds the first time" do
31
+ met_block_calls = 0
32
+ meet_block_calls = 0
33
+
34
+ @stub.new.instance_eval do
35
+ met? do
36
+ met_block_calls += 1
37
+ true
38
+ end
39
+ meet { meet_block_calls += 1 }
40
+ end
41
+
42
+ met_block_calls.should == 1
43
+ meet_block_calls.should == 0
44
+ end
45
+
46
+ it "should raise if the met? block fails twice" do
47
+ met_block_calls = 0
48
+ meet_block_calls = 0
49
+
50
+ expect do
51
+ @stub.new.instance_eval do
52
+ met? do
53
+ met_block_calls += 1
54
+ false
55
+ end
56
+ meet { meet_block_calls += 1 }
57
+ end
58
+ end.should raise_error(CouldNotMeetError)
59
+
60
+ met_block_calls.should == 2
61
+ meet_block_calls.should == 1
62
+ end
63
+
64
+ it "should raise an error if there's a meet block without a met block" do
65
+ expect do
66
+ @stub.new.instance_eval do
67
+ meet { }
68
+ end
69
+ end.should raise_error(MeetWithoutMetError)
70
+ end
71
+
72
+ end
73
+ end
74
+
@@ -1,25 +1,37 @@
1
1
  require 'tango'
2
2
 
3
+ class StubLogger
4
+ def enter(name); end
5
+ def leave(name); end
6
+ def log(message); end
7
+ end
8
+
9
+ class StubbedNamespace < Tango::Namespace
10
+ def self.logger
11
+ @logger ||= StubLogger.new
12
+ end
13
+ end
14
+
3
15
  module Tango
4
- describe Dance do
16
+ describe Namespace do
5
17
 
6
18
  it "should run a step" do
7
19
  step_run = false
8
20
 
9
- dance = Dance.new do
21
+ namespace = Class.new(StubbedNamespace) do
10
22
  step "example step" do
11
23
  step_run = true
12
24
  end
13
25
  end
14
26
 
15
- dance.run "example step"
27
+ namespace.run "example step"
16
28
  step_run.should be_true
17
29
  end
18
30
 
19
31
  it "should run one step from within another" do
20
32
  inner_step_run = false
21
33
 
22
- dance = Dance.new do
34
+ namespace = Class.new(StubbedNamespace) do
23
35
  step "outer step" do
24
36
  run "inner step"
25
37
  end
@@ -29,24 +41,24 @@ module Tango
29
41
  end
30
42
  end
31
43
 
32
- dance.run "outer step"
44
+ namespace.run "outer step"
33
45
  inner_step_run.should be_true
34
46
  end
35
47
 
36
48
  context "passing arguments" do
37
49
  it "should pass arguments to a step" do
38
- dance = Dance.new do
50
+ namespace = Class.new(StubbedNamespace) do
39
51
  step "example step" do |a, b|
40
52
  a.should == 1
41
53
  b.should == 2
42
54
  end
43
55
  end
44
56
 
45
- dance.run "example step", 1, 2
57
+ namespace.run "example step", 1, 2
46
58
  end
47
59
 
48
60
  it "should pass arguments when running other steps" do
49
- dance = Dance.new do
61
+ namespace = Class.new(StubbedNamespace) do
50
62
  step "outer step" do
51
63
  run "inner step", 1, 2
52
64
  end
@@ -57,26 +69,7 @@ module Tango
57
69
  end
58
70
  end
59
71
 
60
- dance.run "outer step"
61
- end
62
- end
63
-
64
- context "error handling" do
65
- it "should raise an error on an attempt to redefine a step" do
66
- expect do
67
- Dance.new do
68
- step "example step" do; end
69
- step "example step" do; end
70
- end
71
- end.should raise_error(StepAlreadyDefinedError)
72
- end
73
-
74
- it "should raise an error on an attempt to run an undefined step" do
75
- dance = Dance.new do; end
76
-
77
- expect do
78
- dance.run "undefined step"
79
- end.should raise_error(UndefinedStepError)
72
+ namespace.run "outer step"
80
73
  end
81
74
  end
82
75
 
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: 25
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 4
10
+ version: 0.0.4
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-03-29 00:00:00 +11:00
18
+ date: 2011-03-30 00:00:00 +11:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -46,20 +46,18 @@ files:
46
46
  - .rspec
47
47
  - Gemfile
48
48
  - Gemfile.lock
49
+ - README.md
49
50
  - Rakefile
50
51
  - bin/tango
51
52
  - lib/tango.rb
52
- - lib/tango/dance.rb
53
- - lib/tango/dance_card.rb
54
- - lib/tango/errors.rb
53
+ - lib/tango/as_user.rb
55
54
  - lib/tango/logger.rb
56
- - lib/tango/noop_logger.rb
57
- - lib/tango/step_runner.rb
55
+ - lib/tango/met_and_meet.rb
56
+ - lib/tango/namespace.rb
58
57
  - lib/tango/version.rb
59
- - spec/dance_card_spec.rb
60
- - spec/dance_spec.rb
61
58
  - spec/logger_spec.rb
62
- - spec/step_runner_spec.rb
59
+ - spec/met_and_meet_spec.rb
60
+ - spec/namespace_spec.rb
63
61
  - tango.gemspec
64
62
  has_rdoc: true
65
63
  homepage: ""
@@ -96,7 +94,6 @@ signing_key:
96
94
  specification_version: 3
97
95
  summary: Experiment in deployment tools.
98
96
  test_files:
99
- - spec/dance_card_spec.rb
100
- - spec/dance_spec.rb
101
97
  - spec/logger_spec.rb
102
- - spec/step_runner_spec.rb
98
+ - spec/met_and_meet_spec.rb
99
+ - spec/namespace_spec.rb
data/lib/tango/dance.rb DELETED
@@ -1,22 +0,0 @@
1
- module Tango
2
- class Dance
3
-
4
- def initialize(dance_card = nil, &block)
5
- @dance_card = dance_card
6
- @steps = {}
7
- instance_eval(&block)
8
- end
9
-
10
- def step(name, &block)
11
- raise StepAlreadyDefinedError, "Step #{name} already defined" if @steps.has_key?(name)
12
- @steps[name] = block
13
- end
14
-
15
- def run(step_name, *args)
16
- step = @steps[step_name]
17
- raise UndefinedStepError, "Step #{step_name} not defined" if step.nil?
18
- StepRunner.new(@dance_card || self).instance_exec(*args, &step)
19
- end
20
-
21
- end
22
- end
@@ -1,32 +0,0 @@
1
- require 'tango/logger'
2
- require 'tango/noop_logger'
3
-
4
- module Tango
5
- class DanceCard
6
-
7
- def self.instance
8
- @dance_card ||= DanceCard.new(Logger.new)
9
- end
10
-
11
- def initialize(logger = nil)
12
- @logger = logger || NoopLogger.new
13
- @dances = {}
14
- end
15
-
16
- def dance(name, &block)
17
- @dances[name] = Dance.new(self, &block)
18
- end
19
-
20
- def run(name, *args)
21
- dance_name, step_name = *name.split(":")
22
- @logger.enter(name)
23
- @dances[dance_name].run(step_name, *args)
24
- @logger.leave(name)
25
- end
26
-
27
- def log(message)
28
- @logger.log(message)
29
- end
30
-
31
- end
32
- end
data/lib/tango/errors.rb DELETED
@@ -1,6 +0,0 @@
1
- module Tango
2
- class StepAlreadyDefinedError < RuntimeError; end
3
- class UndefinedStepError < RuntimeError; end
4
- class CouldNotMeetError < RuntimeError; end
5
- class MeetWithoutMetError < RuntimeError; end
6
- end
@@ -1,15 +0,0 @@
1
- module Tango
2
- class NoopLogger
3
-
4
- def enter(step_name)
5
- end
6
-
7
- def log(message)
8
- end
9
-
10
- def leave(step_name)
11
- end
12
-
13
- end
14
- end
15
-
@@ -1,50 +0,0 @@
1
- module Tango
2
- # A step's block is instance_execed against one of these. It provides all the
3
- # methods accessible from within the step.
4
- class StepRunner
5
-
6
- def initialize(context = nil)
7
- @context = context
8
- end
9
-
10
- def met?(&met_block)
11
- @met_block = met_block
12
- end
13
-
14
- def meet(&meet_block)
15
- raise MeetWithoutMetError if @met_block.nil?
16
- if instance_eval(&@met_block)
17
- log "already met."
18
- else
19
- log "not already met."
20
- instance_eval(&meet_block)
21
- if instance_eval(&@met_block)
22
- log "met."
23
- else
24
- raise CouldNotMeetError
25
- end
26
- end
27
- end
28
-
29
- def run(step_name, *args)
30
- @context.run(step_name, *args)
31
- end
32
-
33
- def as(username)
34
- info = Etc.getpwent(username)
35
- uid, gid = Process.euid, Process.egid
36
- Process::Sys.seteuid(0) if uid != 0
37
- Process::Sys.setegid(info.gid)
38
- Process::Sys.seteuid(info.uid)
39
- yield
40
- ensure
41
- Process::Sys.seteuid(uid)
42
- Process::Sys.setegid(gid)
43
- end
44
-
45
- def log(message)
46
- @context.log(message) unless @context.nil?
47
- end
48
-
49
- end
50
- end
@@ -1,56 +0,0 @@
1
- require 'tango'
2
-
3
- module Tango
4
- describe DanceCard do
5
-
6
- it "should run a step in a dance by name" do
7
- step_run = false
8
- card = DanceCard.new
9
- card.dance "example dance" do
10
- step "example step" do
11
- step_run = true
12
- end
13
- end
14
-
15
- card.run "example dance:example step"
16
-
17
- step_run.should be_true
18
- end
19
-
20
- it "should pass arguments to a step" do
21
- card = DanceCard.new
22
- card.dance "example dance" do
23
- step "example step" do |a, b|
24
- a.should == 1
25
- b.should == 2
26
- end
27
- end
28
-
29
- card.run "example dance:example step", 1, 2
30
- end
31
-
32
- it "should call a step in another dance by name" do
33
- step_run = false
34
-
35
- card = DanceCard.new
36
-
37
- card.dance "foxtrot" do
38
- step "foxtrot step" do
39
- step_run = true
40
- end
41
- end
42
-
43
- card.dance "flamenco" do
44
- step "flamenco step" do
45
- run "foxtrot:foxtrot step"
46
- end
47
- end
48
-
49
- card.run "flamenco:flamenco step"
50
-
51
- step_run.should be_true
52
- end
53
-
54
- end
55
- end
56
-
@@ -1,67 +0,0 @@
1
- require 'tango'
2
-
3
- module Tango
4
- describe StepRunner do
5
-
6
- context "with a meet block and a met block" do
7
- it "should check the met?, run the meet, then check the met? again" do
8
- met_block_calls = 0
9
- meet_block_calls = 0
10
-
11
- StepRunner.new.instance_eval do
12
- met? do
13
- met_block_calls += 1
14
- meet_block_calls > 0
15
- end
16
- meet { meet_block_calls += 1 }
17
- end
18
-
19
- met_block_calls.should == 2
20
- meet_block_calls.should == 1
21
- end
22
-
23
- it "should not run the meet if the met? succeeds the first time" do
24
- met_block_calls = 0
25
- meet_block_calls = 0
26
-
27
- StepRunner.new.instance_eval do
28
- met? do
29
- met_block_calls += 1
30
- true
31
- end
32
- meet { meet_block_calls += 1 }
33
- end
34
-
35
- met_block_calls.should == 1
36
- meet_block_calls.should == 0
37
- end
38
-
39
- it "should raise if the met? block fails twice" do
40
- met_block_calls = 0
41
- meet_block_calls = 0
42
-
43
- expect do
44
- StepRunner.new.instance_eval do
45
- met? do
46
- met_block_calls += 1
47
- false
48
- end
49
- meet { meet_block_calls += 1 }
50
- end
51
- end.should raise_error(CouldNotMeetError)
52
-
53
- met_block_calls.should == 2
54
- meet_block_calls.should == 1
55
- end
56
-
57
- it "should raise an error if there's a meet block without a met block" do
58
- expect do
59
- StepRunner.new.instance_eval do
60
- meet { }
61
- end
62
- end.should raise_error(MeetWithoutMetError)
63
- end
64
- end
65
-
66
- end
67
- end