taketo 0.0.5 → 0.0.6

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/README.md CHANGED
@@ -78,11 +78,37 @@ Destination resolving works intelligently. Given the following config:
78
78
 
79
79
  ```taketo my_project:staging``` will ssh to s1 with host = 1.2.3.4
80
80
  ```taketo my_project2``` will ssh to s2 with host = 2.3.4.5
81
- ```taketo mps2``` will ssh to s2 with host = 3.4.5.6 - note the use of global alias
81
+ ```taketo mps1``` will ssh to ps1 with host = 3.4.5.6 - note the use of global alias
82
82
 
83
83
  Note that default destination can be specified via ```default_destination``` config option
84
84
 
85
-
85
+ You can use shared server configs to reduce duplication:
86
+
87
+ ```ruby
88
+ shared_server_config :my_staging do
89
+ command :console do
90
+ execute "rails c"
91
+ desc "Launch rails console"
92
+ end
93
+ end
94
+
95
+ project :my_project do
96
+ environment :staging do
97
+ server :s1 do
98
+ host "1.2.3.4"
99
+ include_shared_server_config(:my_staging)
100
+ end
101
+
102
+ server :s2 do
103
+ host :s2 do
104
+ include_shared_server_config(:my_staging)
105
+ end
106
+ end
107
+ end
108
+ ```
109
+
110
+ This will give you ```console``` commands available both on s1 and s2
111
+
86
112
  To-Do:
87
113
  ------
88
114
 
@@ -92,6 +118,10 @@ To-Do:
92
118
  The Changelog:
93
119
  --------------
94
120
 
121
+ ### v0.0.6 (26.07.2012) ###
122
+ * Add identity_file server config option
123
+ * Add shared server config support
124
+
95
125
  ### v0.0.5 (24.07.2012) ###
96
126
  * Add --directory option, which enables specifying directory on remote server upon launch
97
127
  * Add global_alias config option for servers
data/Rakefile CHANGED
@@ -15,7 +15,14 @@ require 'rspec/core/rake_task'
15
15
  require 'cucumber'
16
16
  require 'cucumber/rake/task'
17
17
 
18
- RSpec::Core::RakeTask.new
18
+ RSpec::Core::RakeTask.new do |t|
19
+ t.pattern = 'spec/lib/**/*_spec.rb'
20
+ end
21
+
22
+ RSpec::Core::RakeTask.new do |t|
23
+ t.pattern = 'spec/integration/**/*_spec.rb'
24
+ t.name = :integration_spec
25
+ end
19
26
 
20
27
  Cucumber::Rake::Task.new(:features) do |t|
21
28
  t.cucumber_opts = "features --tags ~@wip --format pretty -x"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
data/bin/taketo CHANGED
@@ -31,7 +31,7 @@ def parse_options
31
31
 
32
32
  OptionParser.new do |opts|
33
33
  opts.banner = "Usage: taketo [destination] [options]"
34
- opts.version = VERSION
34
+ opts.version = ::Taketo::VERSION
35
35
  opts.separator ""
36
36
  opts.separator "Common options:"
37
37
 
@@ -0,0 +1,90 @@
1
+ Feature: taketo config
2
+ In order to get rid of routineous ssh command calls
3
+ As a user
4
+ I want to be able configure taketo
5
+
6
+ Scenario: Shared server configs
7
+ When I have the following config in "/tmp/taketo_test_cfg.rb"
8
+ """
9
+ shared_server_config :shared_config_example do
10
+ port 9999 #can contain any server config options
11
+ end
12
+
13
+ project :slots do
14
+ environment :staging do
15
+ server(:s1) { host "1.2.3.4"; include_shared_server_config(:shared_config_example) }
16
+ end
17
+ end
18
+ """
19
+ And I successfully run `taketo slots:staging:s1 --config=/tmp/taketo_test_cfg.rb --dry-run`
20
+ Then the output should contain
21
+ """
22
+ ssh -t -p 9999 1.2.3.4 "RAILS_ENV=staging bash"
23
+ """
24
+
25
+ Scenario: Set environment variables
26
+ When I have the following config in "/tmp/taketo_test_cfg.rb"
27
+ """
28
+ project :slots do
29
+ environment :staging do
30
+ server do
31
+ host "1.2.3.4"
32
+ location "/var/apps/slots"
33
+ env :FOO => "the value"
34
+ end
35
+ end
36
+ end
37
+ """
38
+ And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run`
39
+ Then the output should contain
40
+ """
41
+ RAILS_ENV=staging
42
+ """
43
+ And the output should contain
44
+ """
45
+ FOO=the\ value
46
+ """
47
+
48
+ Scenario: Reopen config scopes
49
+ When I have the following config in "/tmp/taketo_test_cfg.rb"
50
+ """
51
+ project :slots do
52
+ environment :staging do
53
+ server do
54
+ host "1.2.3.4"
55
+ end
56
+ end
57
+ end
58
+
59
+ project :slots do
60
+ environment :staging do
61
+ server do
62
+ env :FOO => "bar"
63
+ end
64
+ end
65
+ end
66
+ """
67
+ And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb slots:staging --dry-run`
68
+ Then the output should match /ssh -t 1\.2\.3\.4 "(RAILS_ENV=staging FOO=bar|FOO=bar RAILS_ENV=staging) bash"/
69
+
70
+ Scenario: Unique server alias
71
+ When I have the following config in "/tmp/taketo_test_cfg.rb"
72
+ """
73
+ project :slots do
74
+ environment :staging do
75
+ server :s1 do
76
+ host "1.2.3.4"
77
+ end
78
+ server :s2 do
79
+ global_alias :ss2
80
+ host "2.3.4.5"
81
+ end
82
+ end
83
+ end
84
+ """
85
+ And I successfully run `taketo ss2 --config=/tmp/taketo_test_cfg.rb --dry-run`
86
+ Then the output should contain
87
+ """
88
+ ssh -t 2.3.4.5 "RAILS_ENV=staging bash"
89
+ """
90
+
@@ -46,51 +46,6 @@ Feature:
46
46
  ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging bash"
47
47
  """
48
48
 
49
- Scenario: Set environment variables
50
- When I have the following config in "/tmp/taketo_test_cfg.rb"
51
- """
52
- project :slots do
53
- environment :staging do
54
- server do
55
- host "1.2.3.4"
56
- location "/var/apps/slots"
57
- env :FOO => "the value"
58
- end
59
- end
60
- end
61
- """
62
- And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run`
63
- Then the output should contain
64
- """
65
- RAILS_ENV=staging
66
- """
67
- And the output should contain
68
- """
69
- FOO=the\ value
70
- """
71
-
72
- Scenario: Reopen config scopes
73
- When I have the following config in "/tmp/taketo_test_cfg.rb"
74
- """
75
- project :slots do
76
- environment :staging do
77
- server do
78
- host "1.2.3.4"
79
- end
80
- end
81
- end
82
-
83
- project :slots do
84
- environment :staging do
85
- server do
86
- env :FOO => "bar"
87
- end
88
- end
89
- end
90
- """
91
- And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb slots:staging --dry-run`
92
- Then the output should match /ssh -t 1\.2\.3\.4 "(RAILS_ENV=staging FOO=bar|FOO=bar RAILS_ENV=staging) bash"/
93
-
94
49
  Scenario: Default destination
95
50
  When I have the following config in "/tmp/taketo_test_cfg.rb"
96
51
  """
@@ -111,23 +66,21 @@ Feature:
111
66
  ssh -t 2.3.4.5 "RAILS_ENV=staging bash"
112
67
  """
113
68
 
114
- Scenario: Unique server alias
69
+ Scenario: SSH key file
115
70
  When I have the following config in "/tmp/taketo_test_cfg.rb"
116
71
  """
117
72
  project :slots do
118
73
  environment :staging do
119
- server :s1 do
120
- host "1.2.3.4"
121
- end
122
- server :s2 do
123
- global_alias :ss2
74
+ server do
75
+ identity_file "/home/gor/.ssh/foo bar"
124
76
  host "2.3.4.5"
125
77
  end
126
78
  end
127
79
  end
128
80
  """
129
- And I successfully run `taketo ss2 --config=/tmp/taketo_test_cfg.rb --dry-run`
81
+ And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run`
130
82
  Then the output should contain
131
83
  """
132
- ssh -t 2.3.4.5 "RAILS_ENV=staging bash"
84
+ ssh -t -i /home/gor/.ssh/foo\ bar 2.3.4.5 "RAILS_ENV=staging bash"
133
85
  """
86
+
@@ -13,7 +13,7 @@ module Taketo
13
13
  end
14
14
 
15
15
  def render(rendered_command)
16
- %Q[ssh -t #{port} #{username}#{host} "#{rendered_command}"].squeeze(" ")
16
+ %Q[ssh -t #{port} #{identity_file} #{username}#{host} "#{rendered_command}"].squeeze(" ")
17
17
  end
18
18
 
19
19
  def host
@@ -30,6 +30,10 @@ module Taketo
30
30
  def username
31
31
  %Q[#{shellescape @server.username}@] if @server.username
32
32
  end
33
+
34
+ def identity_file
35
+ %Q[-i #{shellescape @server.identity_file}] if @server.identity_file
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -7,7 +7,7 @@ module Taketo
7
7
  module Constructs
8
8
  class Server < BaseConstruct
9
9
  attr_reader :environment_variables
10
- attr_accessor :host, :port, :username, :default_location, :environment, :global_alias
10
+ attr_accessor :host, :port, :username, :default_location, :environment, :global_alias, :identity_file
11
11
 
12
12
  has_nodes :commands, :command
13
13
 
data/lib/taketo/dsl.rb CHANGED
@@ -2,7 +2,8 @@ require 'taketo/constructs_factory'
2
2
 
3
3
  module Taketo
4
4
  class DSL
5
- class ScopeError < StandardError; end
5
+ class ScopeError < StandardError; end
6
+ class ConfigError < StandardError; end
6
7
 
7
8
  class << self
8
9
  def define_scope(scope, parent_scope, options = {})
@@ -19,23 +20,25 @@ module Taketo
19
20
  end
20
21
  end
21
22
 
22
- def define_attribute(name, parent_scope, &block)
23
- define_method name do |attribute|
23
+ def define_method_in_scope(name, parent_scope, &block)
24
+ define_method name do |*args, &blk|
24
25
  unless current_scope?(parent_scope)
25
26
  raise ScopeError,
26
27
  "#{name} can't be defined in #{current_scope} scope"
27
28
  end
28
- instance_exec(attribute, &block)
29
+ args.push blk if blk
30
+ instance_exec(*args, &block)
29
31
  end
30
32
  end
31
33
  end
32
34
 
33
- attr_reader :current_scope_object, :config
35
+ attr_reader :current_scope_object, :config, :shared_server_configs
34
36
 
35
37
  def initialize(factory = Taketo::ConstructsFactory.new)
36
38
  @factory = factory
37
39
  @scope = [:config]
38
40
  @config = @current_scope_object = factory.create_config
41
+ @shared_server_configs = Hash.new { |h, k| raise ConfigError, "Shared server config '#{k}' is not defined!"}
39
42
  end
40
43
 
41
44
  def configure(filename = nil, &block)
@@ -56,15 +59,24 @@ module Taketo
56
59
  define_scope :server, :environment, :default_name => :default
57
60
  define_scope :command, :server
58
61
 
59
- define_attribute(:default_destination, :config) { |destination| current_scope_object.default_destination = destination }
60
- define_attribute(:host, :server) { |hostname| current_scope_object.host = hostname }
61
- define_attribute(:port, :server) { |port_number| current_scope_object.port = port_number }
62
- define_attribute(:user, :server) { |username| current_scope_object.username = username }
63
- define_attribute(:location, :server) { |path| current_scope_object.default_location = path }
64
- define_attribute(:global_alias,:server) { |alias_name| current_scope_object.global_alias = alias_name }
65
- define_attribute(:env, :server) { |env| current_scope_object.env(env) }
66
- define_attribute(:execute, :command) { |command| current_scope_object.command = command }
67
- define_attribute(:desc, :command) { |description| current_scope_object.description = description }
62
+ define_method_in_scope(:default_destination, :config) { |destination| current_scope_object.default_destination = destination }
63
+ define_method_in_scope(:host, :server) { |hostname| current_scope_object.host = hostname }
64
+ define_method_in_scope(:port, :server) { |port_number| current_scope_object.port = port_number }
65
+ define_method_in_scope(:user, :server) { |username| current_scope_object.username = username }
66
+ define_method_in_scope(:location, :server) { |path| current_scope_object.default_location = path }
67
+ define_method_in_scope(:global_alias,:server) { |alias_name| current_scope_object.global_alias = alias_name }
68
+ define_method_in_scope(:env, :server) { |env| current_scope_object.env(env) }
69
+ define_method_in_scope(:identity_file, :server) { |identity_file| current_scope_object.identity_file = identity_file }
70
+ define_method_in_scope(:execute, :command) { |command| current_scope_object.command = command }
71
+ define_method_in_scope(:desc, :command) { |description| current_scope_object.description = description }
72
+
73
+ define_method_in_scope(:shared_server_config, :config) do |name, blk|
74
+ @shared_server_configs.store(name.to_sym, blk)
75
+ end
76
+
77
+ define_method_in_scope(:include_shared_server_config, :server) do |name, *args|
78
+ instance_exec(*args, &shared_server_configs[name])
79
+ end
68
80
 
69
81
  private
70
82
 
@@ -7,7 +7,7 @@ module Taketo
7
7
  include Enumerable
8
8
  extend Forwardable
9
9
 
10
- def_delegators :@nodes, :each, :length, :size, :empty?
10
+ def_delegators :@nodes, :each, :length, :size, :empty?, :first, :last
11
11
 
12
12
  def initialize(nodes = [])
13
13
  @nodes = nodes
data/lib/taketo.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Taketo
2
2
  version_file = File.expand_path('../VERSION', File.dirname(__FILE__))
3
- VERSION = File.read(version_file).freeze unless defined? VERSION
3
+ VERSION = File.read(version_file).freeze
4
4
  end
5
5
 
6
6
  require 'taketo/support'
@@ -5,6 +5,13 @@ describe "Taketo DSL" do
5
5
  it "should parse config and instantiate objects" do
6
6
  factory = Taketo::ConstructsFactory.new
7
7
  config = Taketo::DSL.new(factory).configure do
8
+ shared_server_config(:commands) do
9
+ command :console do
10
+ execute "rails c"
11
+ desc "Rails console"
12
+ end
13
+ end
14
+
8
15
  project :slots do
9
16
  environment :staging do
10
17
  server do
@@ -12,9 +19,7 @@ describe "Taketo DSL" do
12
19
  user "deployer"
13
20
  location "/var/app"
14
21
  env :FOO => "bar"
15
- command :console do
16
- execute "rails c"
17
- end
22
+ include_shared_server_config :commands
18
23
  end
19
24
  end
20
25
 
@@ -26,6 +31,7 @@ describe "Taketo DSL" do
26
31
  server server_name do
27
32
  host host_name
28
33
  location "/var/app"
34
+ include_shared_server_config :commands
29
35
  end
30
36
  end
31
37
  end
@@ -46,11 +52,15 @@ describe "Taketo DSL" do
46
52
  staging_server.username.should == "deployer"
47
53
  staging_server.default_location.should == "/var/app"
48
54
  staging_server.environment_variables.should == { :RAILS_ENV => "staging", :FOO => "bar" }
49
- staging_server.commands.length.should == 1
50
- staging_server.commands[:console].command.should == "rails c"
51
55
 
52
56
  production = project.environments[:production]
53
57
  production.servers.length.should == 2
58
+ production_server_1, production_server_2 = production.servers.first, production.servers.last
59
+
60
+ [staging_server, production_server_1, production_server_2].each do |s|
61
+ s.commands.length.should == 1
62
+ s.commands[:console].command.should == "rails c"
63
+ end
54
64
  end
55
65
  end
56
66
 
@@ -11,6 +11,7 @@ describe "SSH Command" do
11
11
  :port => 22,
12
12
  :username => "deployer",
13
13
  :default_location => "/var/app",
14
+ :identity_file => "/home/gor/.ssh/qqq",
14
15
  :environment => environment,
15
16
  :environment_variables => {})
16
17
  end
@@ -19,12 +20,13 @@ describe "SSH Command" do
19
20
  let(:ssh_command) { SSHCommand.new(server) }
20
21
 
21
22
  it "should compose command based on provided server object" do
22
- ssh_command.render("foobar").should == %q[ssh -t -p 22 deployer@1.2.3.4 "foobar"]
23
+ ssh_command.render("foobar").should == %q[ssh -t -p 22 -i /home/gor/.ssh/qqq deployer@1.2.3.4 "foobar"]
23
24
  end
24
25
 
25
26
  it "should ignore absent parts" do
26
27
  server.stub(:port => nil)
27
28
  server.stub(:username => nil)
29
+ server.stub(:identity_file => nil)
28
30
  ssh_command.render("foobar").should == %q[ssh -t 1.2.3.4 "foobar"]
29
31
  end
30
32
 
@@ -16,6 +16,7 @@ describe "Server" do
16
16
  it { should have_accessor(:username) }
17
17
  it { should have_accessor(:default_location) }
18
18
  it { should have_accessor(:global_alias) }
19
+ it { should have_accessor(:identity_file) }
19
20
 
20
21
  describe "#environment=" do
21
22
  let(:environment) { environment = stub(:Environment, :name => :the_environment) }
@@ -48,7 +48,7 @@ describe "DSL" do
48
48
  end # end
49
49
  end
50
50
 
51
- shared_examples "an attribute" do |attribute_name, parent_scope_name, parent_scope_method, example_value|
51
+ shared_examples "a scoped method" do |attribute_name, parent_scope_name, parent_scope_method, example_value|
52
52
  parent_scope = scopes[parent_scope_name]
53
53
 
54
54
  it { should be_appropriate_construct(attribute_name, example_value).under(parent_scope) }
@@ -66,7 +66,41 @@ describe "DSL" do
66
66
  end
67
67
 
68
68
  describe "#default_destination" do
69
- it_behaves_like "an attribute", :default_destination, :config, :default_destination=, "foo:bar:baz"
69
+ it_behaves_like "a scoped method", :default_destination, :config, :default_destination=, "foo:bar:baz"
70
+ end
71
+
72
+ describe "Shared server config" do
73
+ specify "#shared_server_config should store a block" do
74
+ dsl(scopes[:config], factory.create(:config)) do |c|
75
+ cfg = proc { any_method_call_here }
76
+ c.shared_server_config(:foo, &cfg)
77
+ c.shared_server_configs[:foo].should == cfg
78
+ end
79
+ end
80
+
81
+ describe "#include_shared_server_config" do
82
+ it "should execute the block on dsl object in server scope" do
83
+ dsl(scopes[:server], factory.create(:server)) do |c|
84
+ c.stub(:shared_server_configs => { :foo => proc { any_method_call_here } })
85
+ c.should_receive(:any_method_call_here)
86
+ c.include_shared_server_config(:foo)
87
+ end
88
+ end
89
+
90
+ it "should accept arguments" do
91
+ dsl(scopes[:server], factory.create(:server)) do |c|
92
+ c.stub(:shared_server_configs => { :foo => proc { |qux| any_method_call_here(qux) } })
93
+ c.should_receive(:any_method_call_here).with(321)
94
+ c.include_shared_server_config(:foo, 321)
95
+ end
96
+ end
97
+
98
+ it "should raise ConfigError if non-existent config included" do
99
+ dsl(scopes[:server], factory.create(:server)) do |c|
100
+ expect { c.include_shared_server_config(:foo) }.to raise_error(Taketo::DSL::ConfigError, "Shared server config 'foo' is not defined!")
101
+ end
102
+ end
103
+ end
70
104
  end
71
105
 
72
106
  describe "#project" do
@@ -88,38 +122,42 @@ describe "DSL" do
88
122
  end
89
123
 
90
124
  describe "#host" do
91
- it_behaves_like "an attribute", :host, :server, :host=, "127.0.0.2"
125
+ it_behaves_like "a scoped method", :host, :server, :host=, "127.0.0.2"
92
126
  end
93
127
 
94
128
  describe "#port" do
95
- it_behaves_like "an attribute", :port, :server, :port=, 4096
129
+ it_behaves_like "a scoped method", :port, :server, :port=, 4096
96
130
  end
97
131
 
98
132
  describe "#user" do
99
- it_behaves_like "an attribute", :user, :server, :username=, "deployer"
133
+ it_behaves_like "a scoped method", :user, :server, :username=, "deployer"
100
134
  end
101
135
 
102
136
  describe "#location" do
103
- it_behaves_like "an attribute", :location, :server, :default_location=, "/var/app/"
137
+ it_behaves_like "a scoped method", :location, :server, :default_location=, "/var/app/"
104
138
  end
105
139
 
106
140
  describe "#env" do
107
- it_behaves_like "an attribute", :env, :server, :env, { :FOO => "bar" }
141
+ it_behaves_like "a scoped method", :env, :server, :env, { :FOO => "bar" }
108
142
  end
109
143
 
110
144
  describe "#global_alias" do
111
- it_behaves_like "an attribute", :global_alias, :server, :global_alias=, "foobared"
145
+ it_behaves_like "a scoped method", :global_alias, :server, :global_alias=, "foobared"
146
+ end
147
+
148
+ describe "#identity_file" do
149
+ it_behaves_like "a scoped method", :identity_file, :server, :identity_file=, "/home/gor/.ssh/qqq"
112
150
  end
113
151
 
114
152
  describe "#command" do
115
153
  it_behaves_like "a scope", :command, :server
116
154
 
117
155
  describe "#execute" do
118
- it_behaves_like "an attribute", :execute, :command, :command=, "rails c"
156
+ it_behaves_like "a scoped method", :execute, :command, :command=, "rails c"
119
157
  end
120
158
 
121
159
  describe "#desc" do
122
- it_behaves_like "an attribute", :desc, :command, :description=, "Run rails console"
160
+ it_behaves_like "a scoped method", :desc, :command, :description=, "Run rails console"
123
161
  end
124
162
  end
125
163
  end
@@ -18,6 +18,8 @@ describe "NamedNodesCollection" do
18
18
  collection.map(&:name).should == [:foo, :bar]
19
19
  collection.length.should == 2
20
20
  collection.size.should == 2
21
+ collection.first.should == node1
22
+ collection.last.should == node2
21
23
  end
22
24
 
23
25
  it "should raise error if element not found" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taketo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-24 00:00:00.000000000 Z
12
+ date: 2012-07-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -124,6 +124,7 @@ files:
124
124
  - spec/support/matchers/enclose_scope_matcher.rb
125
125
  - spec/support/matchers/have_accessor_matcher.rb
126
126
  - features/commands.feature
127
+ - features/config.feature
127
128
  - features/config_validation.feature
128
129
  - features/connect_to_server.feature
129
130
  - features/error_handling.feature