tango 0.0.3 → 0.0.4

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/.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