taketo 0.0.7 → 0.0.8
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 +34 -7
- data/VERSION +1 -1
- data/features/commands.feature +5 -5
- data/features/config.feature +11 -11
- data/features/config_validation.feature +6 -6
- data/features/connect_to_server.feature +8 -8
- data/features/default_server_config.feature +41 -0
- data/features/error_handling.feature +3 -3
- data/features/help.feature +4 -4
- data/features/step_definitions/main_steps.rb +9 -3
- data/lib/taketo/constructs/base_construct.rb +13 -1
- data/lib/taketo/constructs/environment.rb +0 -5
- data/lib/taketo/constructs/server.rb +2 -1
- data/lib/taketo/dsl.rb +36 -24
- data/spec/integration/dsl_integration_spec.rb +2 -2
- data/spec/lib/taketo/config_validator_spec.rb +7 -7
- data/spec/lib/taketo/constructs/base_construct_spec.rb +30 -0
- data/spec/lib/taketo/constructs/environment_spec.rb +1 -7
- data/spec/lib/taketo/constructs/project_spec.rb +1 -1
- data/spec/lib/taketo/constructs/server_spec.rb +3 -3
- data/spec/lib/taketo/dsl_spec.rb +66 -15
- data/spec/support/helpers/dsl_spec_helper.rb +5 -5
- metadata +3 -2
data/README.md
CHANGED
@@ -66,7 +66,7 @@ Destination resolving works intelligently. Given the following config:
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
project :my_project2 do
|
71
71
|
environment :staging do
|
72
72
|
server :s2 do
|
@@ -76,8 +76,8 @@ Destination resolving works intelligently. Given the following config:
|
|
76
76
|
end
|
77
77
|
```
|
78
78
|
|
79
|
-
```taketo my_project:staging``` will ssh to s1 with host = 1.2.3.4
|
80
|
-
```taketo my_project2``` will ssh to s2 with host = 2.3.4.5
|
79
|
+
```taketo my_project:staging``` will ssh to s1 with host = 1.2.3.4
|
80
|
+
```taketo my_project2``` will ssh to s2 with host = 2.3.4.5
|
81
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
|
@@ -105,29 +105,45 @@ You can use shared server configs to reduce duplication:
|
|
105
105
|
|
106
106
|
server :s2 do
|
107
107
|
host :s2 do
|
108
|
-
include_shared_server_config(:my_staging
|
108
|
+
include_shared_server_config(:my_staging, :some_other_shared_config => "qux")
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
112
112
|
```
|
113
113
|
|
114
|
-
This will give you ```console``` commands available both on s1 and s2
|
114
|
+
This will give you ```console``` commands available both on s1 and s2
|
115
115
|
|
116
116
|
The Changelog:
|
117
117
|
--------------
|
118
118
|
|
119
|
+
### v0.0.8 (17.11.2012) ###
|
120
|
+
* Add per-config, per-project and per-environment default server config support, i.e.
|
121
|
+
```ruby
|
122
|
+
default_server_config { env :TERM => 'xterm-256color' } # Global default server config
|
123
|
+
|
124
|
+
project :p1 do
|
125
|
+
default_server_config { env :FOO => 'bar' } # global default server config is merged
|
126
|
+
...
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
* Shared server configs can be included without redundant empty-array arguments, i.e.
|
131
|
+
```ruby
|
132
|
+
include_shared_server_configs(:foo, :bar, :baz => [:arg1, :arg2], :qux => :arg3)
|
133
|
+
```
|
134
|
+
|
119
135
|
### v0.0.7 (08.10.2012) ###
|
120
136
|
* Add ability to include several shared server config at once
|
121
137
|
Use hash as include_shared_server_config parameter to include
|
122
138
|
multiple shared server configs with arguments, like:
|
123
139
|
```ruby
|
124
|
-
|
140
|
+
include_shared_server_configs(:foo => :some_arg, :bar => [:arg1, :arg2])
|
125
141
|
```
|
126
142
|
or just enumerate them if no arguments needed:
|
127
143
|
```ruby
|
128
144
|
include_shared_server_configs(:baz, :quux)
|
129
145
|
```
|
130
|
-
|
146
|
+
|
131
147
|
NOTE: This change will break your config if you've used parametrized
|
132
148
|
shared server configs before; rewrite them using hash-form
|
133
149
|
|
@@ -155,3 +171,14 @@ The Changelog:
|
|
155
171
|
* Initial release
|
156
172
|
* Support for simplest configs
|
157
173
|
|
174
|
+
|
175
|
+
TO-DO:
|
176
|
+
------
|
177
|
+
|
178
|
+
* Shared server configs without arguments
|
179
|
+
* Global server defaults
|
180
|
+
* Override default commands per server
|
181
|
+
* Define servers outside projects and environments
|
182
|
+
* Export SSH config (i.e. for scp)
|
183
|
+
* Destination completion
|
184
|
+
* Command completion
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.8
|
data/features/commands.feature
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
Feature:
|
1
|
+
Feature:
|
2
2
|
In order to be able to quickly run commands on my servers
|
3
3
|
As a developer
|
4
4
|
I want to have ability to create command shortcuts via config
|
5
5
|
or specify command directly
|
6
6
|
|
7
7
|
Background:
|
8
|
-
When I have the following config
|
8
|
+
When I have the following config
|
9
9
|
"""
|
10
10
|
project :slots do
|
11
11
|
environment :staging do
|
@@ -21,21 +21,21 @@ Feature:
|
|
21
21
|
"""
|
22
22
|
|
23
23
|
Scenario: Run explicit command
|
24
|
-
When I
|
24
|
+
When I run taketo --dry-run --command "TERM=xterm-256color bash"
|
25
25
|
Then the output should contain
|
26
26
|
"""
|
27
27
|
ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging TERM=xterm-256color bash"
|
28
28
|
"""
|
29
29
|
|
30
30
|
Scenario: Run command defined in config
|
31
|
-
When I
|
31
|
+
When I run taketo --dry-run --command console slots:staging
|
32
32
|
Then the output should contain
|
33
33
|
"""
|
34
34
|
ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging rails c"
|
35
35
|
"""
|
36
36
|
|
37
37
|
Scenario: Override default location specified for server
|
38
|
-
When I
|
38
|
+
When I run taketo --dry-run --directory /var/www slots:staging
|
39
39
|
Then the output should contain
|
40
40
|
"""
|
41
41
|
ssh -t 1.2.3.4 "cd /var/www; RAILS_ENV=staging bash"
|
data/features/config.feature
CHANGED
@@ -4,7 +4,7 @@ Feature: taketo config
|
|
4
4
|
I want to be able configure taketo
|
5
5
|
|
6
6
|
Scenario: Shared server configs
|
7
|
-
When I have the following config
|
7
|
+
When I have the following config
|
8
8
|
"""
|
9
9
|
shared_server_config :sc1 do
|
10
10
|
port 9999 #can contain any server config options
|
@@ -20,14 +20,14 @@ Feature: taketo config
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
"""
|
23
|
-
And I
|
23
|
+
And I run taketo slots:staging:s1 --dry-run
|
24
24
|
Then the output should contain
|
25
25
|
"""
|
26
26
|
ssh -t -p 9999 1.2.3.4 "cd /var/qux; RAILS_ENV=staging bash"
|
27
27
|
"""
|
28
28
|
|
29
29
|
Scenario: Shared server configs with arguments
|
30
|
-
When I have the following config
|
30
|
+
When I have the following config
|
31
31
|
"""
|
32
32
|
shared_server_config :sc_args1 do |port_num|
|
33
33
|
port port_num
|
@@ -46,14 +46,14 @@ Feature: taketo config
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
"""
|
49
|
-
And I
|
49
|
+
And I run taketo slots:staging:s1 --dry-run
|
50
50
|
Then the output should contain
|
51
51
|
"""
|
52
52
|
ssh -t -p 9999 1.2.3.4 "cd /var/qux; RAILS_ENV=staging bash"
|
53
53
|
"""
|
54
54
|
|
55
55
|
Scenario: Set environment variables
|
56
|
-
When I have the following config
|
56
|
+
When I have the following config
|
57
57
|
"""
|
58
58
|
project :slots do
|
59
59
|
environment :staging do
|
@@ -65,7 +65,7 @@ Feature: taketo config
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
"""
|
68
|
-
And I
|
68
|
+
And I run taketo --dry-run
|
69
69
|
Then the output should contain
|
70
70
|
"""
|
71
71
|
RAILS_ENV=staging
|
@@ -74,9 +74,9 @@ Feature: taketo config
|
|
74
74
|
"""
|
75
75
|
FOO=the\ value
|
76
76
|
"""
|
77
|
-
|
77
|
+
|
78
78
|
Scenario: Reopen config scopes
|
79
|
-
When I have the following config
|
79
|
+
When I have the following config
|
80
80
|
"""
|
81
81
|
project :slots do
|
82
82
|
environment :staging do
|
@@ -94,11 +94,11 @@ Feature: taketo config
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
"""
|
97
|
-
And I
|
97
|
+
And I run taketo slots:staging --dry-run
|
98
98
|
Then the output should match /ssh -t 1\.2\.3\.4 "(RAILS_ENV=staging FOO=bar|FOO=bar RAILS_ENV=staging) bash"/
|
99
99
|
|
100
100
|
Scenario: Unique server alias
|
101
|
-
When I have the following config
|
101
|
+
When I have the following config
|
102
102
|
"""
|
103
103
|
project :slots do
|
104
104
|
environment :staging do
|
@@ -112,7 +112,7 @@ Feature: taketo config
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
"""
|
115
|
-
And I
|
115
|
+
And I run taketo ss2 --dry-run
|
116
116
|
Then the output should contain
|
117
117
|
"""
|
118
118
|
ssh -t 2.3.4.5 "RAILS_ENV=staging bash"
|
@@ -4,11 +4,11 @@ Feature:
|
|
4
4
|
I want to be guided if there are any errors in my configuration
|
5
5
|
|
6
6
|
Scenario Outline: Config validation
|
7
|
-
When I have the following config
|
7
|
+
When I have the following config
|
8
8
|
"""
|
9
9
|
<config>
|
10
10
|
"""
|
11
|
-
And I run
|
11
|
+
And I run taketo
|
12
12
|
Then the stderr should contain "<error>"
|
13
13
|
|
14
14
|
Examples:
|
@@ -19,18 +19,18 @@ Feature:
|
|
19
19
|
| project(:foo) { environment(:bar) { server {} }} | Server foo:bar:default: host is not defined |
|
20
20
|
|
21
21
|
Scenario: Global server alias clash
|
22
|
-
When I have the following config
|
22
|
+
When I have the following config
|
23
23
|
"""
|
24
24
|
project(:foo) { environment(:bar) {
|
25
25
|
server(:s1) { host '1.2.3.4'; global_alias :a1 }
|
26
26
|
server(:s2) { host '2.3.4.5'; global_alias :a1 }
|
27
27
|
}}
|
28
28
|
"""
|
29
|
-
And I run
|
29
|
+
And I run taketo
|
30
30
|
Then the stderr should contain "Server foo:bar:s2: global alias 'a1' has already been taken by server foo:bar:s1"
|
31
31
|
|
32
32
|
Scenario: Bad command
|
33
|
-
When I have the following config
|
33
|
+
When I have the following config
|
34
34
|
"""
|
35
35
|
project(:foo) { environment(:bar) {
|
36
36
|
server(:s1) { host '1.2.3.4'
|
@@ -38,6 +38,6 @@ Feature:
|
|
38
38
|
}
|
39
39
|
}}
|
40
40
|
"""
|
41
|
-
And I run
|
41
|
+
And I run taketo
|
42
42
|
Then the stderr should contain "Don't know what to execute on command foo"
|
43
43
|
|
@@ -5,7 +5,7 @@ Feature:
|
|
5
5
|
configurable with simple DSL
|
6
6
|
|
7
7
|
Scenario: SSH to server
|
8
|
-
When I have the following config
|
8
|
+
When I have the following config
|
9
9
|
"""
|
10
10
|
project :slots do
|
11
11
|
environment :staging do
|
@@ -22,14 +22,14 @@ Feature:
|
|
22
22
|
end
|
23
23
|
|
24
24
|
"""
|
25
|
-
And I
|
25
|
+
And I run taketo --dry-run slots:staging:s1
|
26
26
|
Then the output should contain
|
27
27
|
"""
|
28
28
|
ssh -t deployer@1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging bash"
|
29
29
|
"""
|
30
30
|
|
31
31
|
Scenario: SSH to the only server
|
32
|
-
When I have the following config
|
32
|
+
When I have the following config
|
33
33
|
"""
|
34
34
|
project :slots do
|
35
35
|
environment :staging do
|
@@ -40,14 +40,14 @@ Feature:
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
"""
|
43
|
-
And I
|
43
|
+
And I run taketo --dry-run
|
44
44
|
Then the output should contain
|
45
45
|
"""
|
46
46
|
ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging bash"
|
47
47
|
"""
|
48
48
|
|
49
49
|
Scenario: Default destination
|
50
|
-
When I have the following config
|
50
|
+
When I have the following config
|
51
51
|
"""
|
52
52
|
default_destination "slots:staging:s2"
|
53
53
|
project :slots do
|
@@ -61,14 +61,14 @@ Feature:
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
"""
|
64
|
-
And I
|
64
|
+
And I run taketo --dry-run
|
65
65
|
Then the output should contain
|
66
66
|
"""
|
67
67
|
ssh -t 2.3.4.5 "RAILS_ENV=staging bash"
|
68
68
|
"""
|
69
69
|
|
70
70
|
Scenario: SSH key file
|
71
|
-
When I have the following config
|
71
|
+
When I have the following config
|
72
72
|
"""
|
73
73
|
project :slots do
|
74
74
|
environment :staging do
|
@@ -79,7 +79,7 @@ Feature:
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
"""
|
82
|
-
And I
|
82
|
+
And I run taketo --dry-run
|
83
83
|
Then the output should contain
|
84
84
|
"""
|
85
85
|
ssh -t -i /home/gor/.ssh/foo\ bar 2.3.4.5 "RAILS_ENV=staging bash"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
Feature: taketo config's default server config
|
2
|
+
In order to reduce duplication
|
3
|
+
As a taketo user
|
4
|
+
I want to be able set default configs for servers in particular scopes
|
5
|
+
|
6
|
+
Background:
|
7
|
+
When I have the following config
|
8
|
+
"""
|
9
|
+
default_server_config do
|
10
|
+
env :FOO => 'bar'
|
11
|
+
end
|
12
|
+
|
13
|
+
project :slots do
|
14
|
+
default_server_config do
|
15
|
+
location '/mnt/apps'
|
16
|
+
end
|
17
|
+
|
18
|
+
environment :staging do
|
19
|
+
server :s1 do
|
20
|
+
host "1.2.3.4"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
project :shoes do
|
26
|
+
environment :production do
|
27
|
+
server do
|
28
|
+
host "2.3.4.5"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
"""
|
33
|
+
|
34
|
+
Scenario: Global default server config
|
35
|
+
When I run taketo shoes --dry-run
|
36
|
+
Then the output should match /ssh -t 2\.3\.4\.5 "(RAILS_ENV=production FOO=bar|FOO=bar RAILS_ENV=production) bash"/
|
37
|
+
|
38
|
+
Scenario: Project default server config
|
39
|
+
When I run taketo slots --dry-run
|
40
|
+
Then the output should match /ssh -t 1\.2\.3\.4 "cd .mnt.apps; (RAILS_ENV=staging FOO=bar|FOO=bar RAILS_ENV=staging) bash"/
|
41
|
+
|
@@ -4,7 +4,7 @@ Feature:
|
|
4
4
|
I want to see meaningful errors when I accidentally specify bad location
|
5
5
|
|
6
6
|
Background:
|
7
|
-
When I have the following config
|
7
|
+
When I have the following config
|
8
8
|
"""
|
9
9
|
default_destination "slots:staging:s2"
|
10
10
|
project :slots do
|
@@ -20,10 +20,10 @@ Feature:
|
|
20
20
|
"""
|
21
21
|
|
22
22
|
Scenario: Non-existent location
|
23
|
-
And I run
|
23
|
+
And I run taketo slots:staging:qqq --dry-run
|
24
24
|
Then the stderr should contain "server qqq not found for environment staging"
|
25
25
|
|
26
26
|
Scenario: Ambiguous location
|
27
|
-
And I run
|
27
|
+
And I run taketo slots:staging --dry-run
|
28
28
|
Then the stderr should contain "There are multiple servers for environment staging: s1, s2"
|
29
29
|
|
data/features/help.feature
CHANGED
@@ -4,7 +4,7 @@ Feature:
|
|
4
4
|
I want to view what's set up in config quickly
|
5
5
|
|
6
6
|
Background:
|
7
|
-
When I have the following config
|
7
|
+
When I have the following config
|
8
8
|
"""
|
9
9
|
project :foo do
|
10
10
|
environment :bar do
|
@@ -34,7 +34,7 @@ Feature:
|
|
34
34
|
"""
|
35
35
|
|
36
36
|
Scenario: View full config
|
37
|
-
When I run
|
37
|
+
When I run taketo --view
|
38
38
|
Then the output should contain exactly:
|
39
39
|
"""
|
40
40
|
|
@@ -55,11 +55,11 @@ Feature:
|
|
55
55
|
Environment: RAILS_ENV=qux
|
56
56
|
console
|
57
57
|
killall - Kill ALL humans
|
58
|
-
|
58
|
+
|
59
59
|
"""
|
60
60
|
|
61
61
|
Scenario: View particular server
|
62
|
-
When I run
|
62
|
+
When I run taketo --view foo:bar:default
|
63
63
|
Then the output should contain exactly:
|
64
64
|
"""
|
65
65
|
Server: default
|
@@ -1,10 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
DEFAULT_TEST_CONFIG_PATH = "/tmp/taketo_test_cfg.rb".freeze
|
2
|
+
|
3
|
+
When /^I have the following config$/ do |config|
|
4
|
+
@config_path = DEFAULT_TEST_CONFIG_PATH
|
5
|
+
File.open(@config_path, "w") do |f|
|
4
6
|
f.write(config)
|
5
7
|
end
|
6
8
|
end
|
7
9
|
|
10
|
+
When /^I run taketo\s?(.*)$/ do |arguments|
|
11
|
+
step "I run `taketo --config=/tmp/taketo_test_cfg.rb #{arguments}`"
|
12
|
+
end
|
13
|
+
|
8
14
|
Then /^the output should contain$/ do |expected|
|
9
15
|
assert_partial_output(expected, all_output)
|
10
16
|
end
|
@@ -6,11 +6,12 @@ module Taketo
|
|
6
6
|
class BaseConstruct
|
7
7
|
|
8
8
|
include AssociatedNodes
|
9
|
-
attr_reader :name
|
9
|
+
attr_reader :name, :default_server_config
|
10
10
|
|
11
11
|
def initialize(name)
|
12
12
|
super
|
13
13
|
@name = name
|
14
|
+
@default_server_config = proc {}
|
14
15
|
end
|
15
16
|
|
16
17
|
def node_type
|
@@ -18,6 +19,17 @@ module Taketo
|
|
18
19
|
demodulized.gsub(/([a-z])([A-Z])/, '\\1_\\2').downcase.to_sym
|
19
20
|
end
|
20
21
|
|
22
|
+
##
|
23
|
+
# Override in subclasses if needed
|
24
|
+
def parent=(parent)
|
25
|
+
@default_server_config = parent.default_server_config
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_server_config=(config)
|
29
|
+
default = @default_server_config
|
30
|
+
@default_server_config = proc { instance_eval(&default); instance_eval(&config) }
|
31
|
+
end
|
32
|
+
|
21
33
|
def qualified_name
|
22
34
|
"#{node_type} #{self.name}"
|
23
35
|
end
|
data/lib/taketo/dsl.rb
CHANGED
@@ -2,30 +2,27 @@ require 'taketo/constructs_factory'
|
|
2
2
|
|
3
3
|
module Taketo
|
4
4
|
class DSL
|
5
|
-
class ScopeError
|
5
|
+
class ScopeError < StandardError; end
|
6
6
|
class ConfigError < StandardError; end
|
7
7
|
|
8
8
|
class << self
|
9
|
-
def define_scope(scope, parent_scope, options = {})
|
10
|
-
define_method scope do |*args, &
|
11
|
-
|
12
|
-
raise ScopeError,
|
13
|
-
"#{scope} can't be defined in #{current_scope} scope"
|
14
|
-
end
|
9
|
+
def define_scope(scope, parent_scope, options = {}, &block)
|
10
|
+
define_method scope do |*args, &blk|
|
11
|
+
ensure_nesting_allowed!(scope, parent_scope)
|
15
12
|
name = args.shift || options[:default_name] or raise(ArgumentError, "Name not specified")
|
13
|
+
|
16
14
|
scope_object = current_scope_object.find(scope, name) { @factory.create(scope, name) }
|
15
|
+
|
17
16
|
in_scope(scope, scope_object) do
|
18
|
-
block
|
17
|
+
instance_exec(current_scope_object, &block) if block
|
18
|
+
blk.call
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def define_method_in_scope(name,
|
23
|
+
def define_method_in_scope(name, *parent_scopes, &block)
|
24
24
|
define_method name do |*args, &blk|
|
25
|
-
|
26
|
-
raise ScopeError,
|
27
|
-
"#{name} can't be defined in #{current_scope} scope"
|
28
|
-
end
|
25
|
+
ensure_nesting_allowed!(name, parent_scopes)
|
29
26
|
args.push blk if blk
|
30
27
|
instance_exec(*args, &block)
|
31
28
|
end
|
@@ -56,7 +53,11 @@ module Taketo
|
|
56
53
|
|
57
54
|
define_scope :project, :config
|
58
55
|
define_scope :environment, :project
|
59
|
-
|
56
|
+
|
57
|
+
define_scope :server, :environment, :default_name => :default do |s|
|
58
|
+
instance_eval(&s.default_server_config)
|
59
|
+
end
|
60
|
+
|
60
61
|
define_scope :command, :server
|
61
62
|
|
62
63
|
define_method_in_scope(:default_destination, :config) { |destination| current_scope_object.default_destination = destination }
|
@@ -70,20 +71,17 @@ module Taketo
|
|
70
71
|
define_method_in_scope(:execute, :command) { |command| current_scope_object.command = command }
|
71
72
|
define_method_in_scope(:desc, :command) { |description| current_scope_object.description = description }
|
72
73
|
|
74
|
+
define_method_in_scope(:default_server_config, :config, :project, :environment) do |blk|
|
75
|
+
current_scope_object.default_server_config = blk
|
76
|
+
end
|
77
|
+
|
73
78
|
define_method_in_scope(:shared_server_config, :config) do |name, blk|
|
74
79
|
@shared_server_configs.store(name.to_sym, blk)
|
75
80
|
end
|
76
81
|
|
77
82
|
define_method_in_scope(:include_shared_server_config, :server) do |*args|
|
78
|
-
|
79
|
-
|
80
|
-
configs_and_arguments.each do |config_name, arguments|
|
81
|
-
instance_exec(*arguments, &shared_server_configs[config_name])
|
82
|
-
end
|
83
|
-
else
|
84
|
-
args.each do |config_name|
|
85
|
-
instance_exec(&shared_server_configs[config_name])
|
86
|
-
end
|
83
|
+
extract_config_names_and_arguments(args).each do |config_name, arguments|
|
84
|
+
instance_exec(*arguments, &shared_server_configs[config_name])
|
87
85
|
end
|
88
86
|
end
|
89
87
|
alias :include_shared_server_configs :include_shared_server_config
|
@@ -106,12 +104,26 @@ module Taketo
|
|
106
104
|
def in_scope(scope, new_scope_object)
|
107
105
|
parent_scope_object, @current_scope_object = @current_scope_object, new_scope_object
|
108
106
|
@scope.push(scope)
|
109
|
-
yield
|
110
107
|
parent_scope_object.send("append_#{scope}", current_scope_object)
|
108
|
+
current_scope_object.parent = parent_scope_object
|
109
|
+
yield
|
111
110
|
@scope.pop
|
112
111
|
@current_scope_object = parent_scope_object
|
113
112
|
end
|
114
113
|
|
114
|
+
def ensure_nesting_allowed!(scope, parent_scopes)
|
115
|
+
if Array(parent_scopes).none? { |s| current_scope?(s) }
|
116
|
+
raise ScopeError, "#{scope} can't be defined in #{current_scope} scope"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def extract_config_names_and_arguments(args)
|
121
|
+
hashes, names = args.partition { |arg| arg.is_a? Hash }
|
122
|
+
configs_from_hashes = hashes.inject({}, &:merge)
|
123
|
+
configs_from_names = Hash[names.map { |config_name| [config_name.to_sym, []] }]
|
124
|
+
configs_from_hashes.merge(configs_from_names)
|
125
|
+
end
|
126
|
+
|
115
127
|
end
|
116
128
|
end
|
117
129
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
require 'taketo/dsl'
|
3
3
|
|
4
4
|
describe "Taketo DSL" do
|
5
|
-
it "
|
5
|
+
it "parses config and instantiate objects" do
|
6
6
|
factory = Taketo::ConstructsFactory.new
|
7
7
|
config = Taketo::DSL.new(factory).configure do
|
8
8
|
shared_server_config(:commands) do
|
@@ -44,7 +44,7 @@ describe "Taketo DSL" do
|
|
44
44
|
|
45
45
|
project.environments.length.should == 2
|
46
46
|
staging = project.environments[:staging]
|
47
|
-
|
47
|
+
|
48
48
|
staging.servers.length.should == 1
|
49
49
|
staging_server = staging.servers[:default]
|
50
50
|
staging_server.name.should == :default
|
@@ -7,7 +7,7 @@ describe "ConfigValidator" do
|
|
7
7
|
let(:traverser) { stub(:ConfigTraverser) }
|
8
8
|
|
9
9
|
describe "#validate!" do
|
10
|
-
it "
|
10
|
+
it "visits all nodes with an instance of ConfigValidator::ConfigValidatorVisitor" do
|
11
11
|
validator = ConfigValidator.new(traverser)
|
12
12
|
traverser.should_receive(:visit_depth_first).with(an_instance_of(ConfigValidator::ConfigValidatorVisitor))
|
13
13
|
validator.validate!
|
@@ -18,7 +18,7 @@ end
|
|
18
18
|
describe "ConfigValidator::ConfigValidatorVisitor" do
|
19
19
|
subject(:visitor) { ConfigValidator::ConfigValidatorVisitor.new }
|
20
20
|
|
21
|
-
it "
|
21
|
+
it "requires config to have projects" do
|
22
22
|
config = stub(:Config, :has_projects? => false)
|
23
23
|
error_message = /no projects/
|
24
24
|
expect { visitor.visit_config(config) }.to raise_error ConfigError, error_message
|
@@ -27,7 +27,7 @@ describe "ConfigValidator::ConfigValidatorVisitor" do
|
|
27
27
|
expect { visitor.visit_config(config) }.not_to raise_error ConfigError, error_message
|
28
28
|
end
|
29
29
|
|
30
|
-
it "
|
30
|
+
it "requires projects to have environments" do
|
31
31
|
project = stub(:Project, :has_environments? => false, :path => "my_project")
|
32
32
|
error_message = /my_project: no environments/
|
33
33
|
expect { visitor.visit_project(project) }.to raise_error ConfigError, error_message
|
@@ -36,7 +36,7 @@ describe "ConfigValidator::ConfigValidatorVisitor" do
|
|
36
36
|
expect { visitor.visit_project(project) }.not_to raise_error ConfigError, error_message
|
37
37
|
end
|
38
38
|
|
39
|
-
it "
|
39
|
+
it "requires environments to have servers" do
|
40
40
|
environment = stub(:Environment, :has_servers? => false, :path => "my_project:my_environment")
|
41
41
|
error_message = /my_project:my_environment: no servers/
|
42
42
|
expect { visitor.visit_environment(environment) }.to raise_error ConfigError, error_message
|
@@ -45,7 +45,7 @@ describe "ConfigValidator::ConfigValidatorVisitor" do
|
|
45
45
|
expect { visitor.visit_environment(environment) }.not_to raise_error ConfigError, error_message
|
46
46
|
end
|
47
47
|
|
48
|
-
it "
|
48
|
+
it "requires servers to have host" do
|
49
49
|
server = stub(:Server, :host => '', :path => "my_project:my_environment:my_server", :global_alias => nil)
|
50
50
|
error_message = /my_project:my_environment:my_server: host is not defined/
|
51
51
|
expect { visitor.visit_server(server) }.to raise_error ConfigError, error_message
|
@@ -54,7 +54,7 @@ describe "ConfigValidator::ConfigValidatorVisitor" do
|
|
54
54
|
expect { visitor.visit_server(server) }.not_to raise_error ConfigError, error_message
|
55
55
|
end
|
56
56
|
|
57
|
-
it "
|
57
|
+
it "requires servers to have unique global server aliases" do
|
58
58
|
server1 = stub(:Server, :host => 'the-host1', :path => "my_project:my_environment:my_server", :global_alias => 'foo')
|
59
59
|
server2 = stub(:Server, :host => 'the-host2', :path => "my_project:my_environment2:my_server3", :global_alias => 'foo')
|
60
60
|
error_message = /my_project:my_environment2:my_server3: global alias 'foo' has already been taken.*my_project:my_environment:my_server/
|
@@ -63,7 +63,7 @@ describe "ConfigValidator::ConfigValidatorVisitor" do
|
|
63
63
|
expect { @visitor.visit_server(server2) }.to raise_error ConfigError, error_message
|
64
64
|
end
|
65
65
|
|
66
|
-
it "
|
66
|
+
it "requires commands to have command specified" do
|
67
67
|
command = stub(:Command, :command => '', :name => 'qux')
|
68
68
|
error_message = /execute/
|
69
69
|
expect { visitor.visit_command(command) }.to raise_error ConfigError, error_message
|
@@ -16,6 +16,36 @@ describe "BaseConstruct" do
|
|
16
16
|
expect(construct.qualified_name).to eq('test_base_construct my_node')
|
17
17
|
end
|
18
18
|
|
19
|
+
specify "#parent= sets default server config to parent's default server config" do
|
20
|
+
parent_default_server_config = proc {}
|
21
|
+
construct.parent = stub(:default_server_config => parent_default_server_config)
|
22
|
+
expect(construct.default_server_config).to eq(parent_default_server_config)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#default_server_config=" do
|
26
|
+
let(:default_server_config) { proc { call_from_self } }
|
27
|
+
let(:context) { stub }
|
28
|
+
|
29
|
+
it "sets default server config" do
|
30
|
+
construct.default_server_config = default_server_config
|
31
|
+
context.should_receive(:call_from_self)
|
32
|
+
context.instance_eval(&construct.default_server_config)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "merges given config to parent's default server config" do
|
36
|
+
construct.parent = stub(:default_server_config => proc { call_from_parent })
|
37
|
+
construct.default_server_config = default_server_config
|
38
|
+
|
39
|
+
context.should_receive(:call_from_parent).ordered
|
40
|
+
context.should_receive(:call_from_self).ordered
|
41
|
+
context.instance_eval(&construct.default_server_config)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has an empty proc as an initial default server config" do
|
46
|
+
expect(construct.default_server_config.call).to eq(nil)
|
47
|
+
end
|
48
|
+
|
19
49
|
end
|
20
50
|
|
21
51
|
|
@@ -13,16 +13,10 @@ describe "Environment" do
|
|
13
13
|
|
14
14
|
it_behaves_like "a construct with nodes", :servers, :server
|
15
15
|
|
16
|
-
specify "#append_server sets environment attribute on a server to self" do
|
17
|
-
server = mock(:Server, :name => :foo)
|
18
|
-
server.should_receive(:environment=).with(environment)
|
19
|
-
environment.append_server(server)
|
20
|
-
end
|
21
|
-
|
22
16
|
specify "#project_name returns project name" do
|
23
17
|
environment.project = stub(:Project, :name => "TheProject")
|
24
18
|
expect(environment.project_name).to eq("TheProject")
|
25
|
-
end
|
19
|
+
end
|
26
20
|
end
|
27
21
|
|
28
22
|
|
@@ -10,7 +10,7 @@ describe "Project" do
|
|
10
10
|
it "has name" do
|
11
11
|
expect(project.name).to eq(:foo)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
specify "#append_environment sets project attribute on an environment to self" do
|
15
15
|
environment = mock(:Environment, :name => :bar)
|
16
16
|
environment.should_receive(:project=).with(project)
|
@@ -30,14 +30,14 @@ describe "Server" do
|
|
30
30
|
expect(server.default_command).to eq(:qux)
|
31
31
|
end
|
32
32
|
|
33
|
-
describe "#
|
34
|
-
let(:environment) { environment = stub(:Environment, :name => :the_environment) }
|
33
|
+
describe "#parent=" do
|
34
|
+
let(:environment) { environment = stub(:Environment, :name => :the_environment, :default_server_config => proc {}) }
|
35
35
|
|
36
36
|
it { should have_accessor(:environment, environment) }
|
37
37
|
|
38
38
|
it "sets RAILS_ENV environment variable" do
|
39
39
|
server.environment_variables.should == {}
|
40
|
-
server.
|
40
|
+
server.parent = environment
|
41
41
|
expect(server.environment_variables[:RAILS_ENV]).to eq(environment.name.to_s)
|
42
42
|
end
|
43
43
|
end
|
data/spec/lib/taketo/dsl_spec.rb
CHANGED
@@ -8,11 +8,15 @@ describe "DSL" do
|
|
8
8
|
extend DSLSpec
|
9
9
|
include DSLSpec
|
10
10
|
|
11
|
-
shared_examples "a scoped construct" do |name,
|
12
|
-
|
13
|
-
|
11
|
+
shared_examples "a scoped construct" do |name, parents, with_block|
|
12
|
+
parents = Array(parents)
|
13
|
+
|
14
|
+
parents.each do |parent_scope_name|
|
15
|
+
parent_scope = scopes[parent_scope_name]
|
16
|
+
it { should be_appropriate_construct(name, :foo).with_block(with_block).under(parent_scope) }
|
17
|
+
end
|
14
18
|
|
15
|
-
scopes.except(
|
19
|
+
scopes.except(*parents).each do |inappropriate_scope|
|
16
20
|
it { should_not be_appropriate_construct(name, :foo).with_block(with_block).under(inappropriate_scope) }
|
17
21
|
end
|
18
22
|
end
|
@@ -52,16 +56,26 @@ describe "DSL" do
|
|
52
56
|
c.send(scope_name, :bar) {} # c.project(:bar) {}
|
53
57
|
end # end
|
54
58
|
end # end
|
59
|
+
|
60
|
+
it "sets #{scope_name}'s parent to the #{parent_scope_name} scope object" do # it "sets project's parent to the config scope object" do
|
61
|
+
dsl(parent_scope, factory.create(parent_scope_name)) do |c| # dsl([:config], factory.create(:config)) do |c|
|
62
|
+
stub_find_or_create_scope_object(c, scope_name, :bar) # stub_find_or_create_scope_object(c, :project, :bar)
|
63
|
+
factory.send(scope_name).should_receive(:parent=).with(c.current_scope_object) # factory.project.should_receive(:parent=).with(c.current_scope_object)
|
64
|
+
c.send(scope_name, :bar) {} # c.project(:bar) {}
|
65
|
+
end # end
|
66
|
+
end #
|
55
67
|
end
|
56
68
|
|
57
|
-
shared_examples "a scoped method" do |attribute_name,
|
58
|
-
it_behaves_like "a scoped construct", attribute_name,
|
69
|
+
shared_examples "a scoped method" do |attribute_name, parent_scope_names, parent_scope_method, example_value|
|
70
|
+
it_behaves_like "a scoped construct", attribute_name, parent_scope_names, false
|
59
71
|
|
60
|
-
|
61
|
-
|
62
|
-
factory.
|
63
|
-
|
64
|
-
|
72
|
+
Array(parent_scope_names).each do |parent_scope_name|
|
73
|
+
it "calls #{parent_scope_method} on current #{parent_scope_name}" do # it "calls default_location= on current server" do
|
74
|
+
dsl(scopes[parent_scope_name], factory.create(parent_scope_name, :foo)) do |c| # dsl([:config, :project, :environment, :server], factory.create(:server, :foo)) do |c|
|
75
|
+
factory.send(parent_scope_name).should_receive(parent_scope_method).with(example_value) # factory.server.should_receive(:default_location=).with('/var/app/')
|
76
|
+
c.send(attribute_name, example_value) # c.location "/var/app"
|
77
|
+
end # end
|
78
|
+
end
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
@@ -69,6 +83,18 @@ describe "DSL" do
|
|
69
83
|
it_behaves_like "a scoped method", :default_destination, :config, :default_destination=, "foo:bar:baz"
|
70
84
|
end
|
71
85
|
|
86
|
+
describe "#default_server_config" do
|
87
|
+
it_behaves_like "a scoped construct", :default_server_config, [:config, :project, :environment]
|
88
|
+
|
89
|
+
it "stores a block" do
|
90
|
+
dsl(scopes[:config], factory.create(:config)) do |c|
|
91
|
+
cfg = proc { any_method_call_here }
|
92
|
+
factory.config.should_receive(:default_server_config=).with(cfg)
|
93
|
+
c.default_server_config(&cfg)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
72
98
|
describe "#shared_server_config" do
|
73
99
|
it_behaves_like "a scoped construct", :shared_server_config, :config
|
74
100
|
|
@@ -84,14 +110,14 @@ describe "DSL" do
|
|
84
110
|
describe "#include_shared_server_config" do
|
85
111
|
it "executes the block on dsl object in server scope for given shared config names" do
|
86
112
|
dsl(scopes[:server], factory.create(:server)) do |c|
|
87
|
-
c.stub(:shared_server_configs => { :foo => proc {
|
88
|
-
c.should_receive(:
|
89
|
-
c.should_receive(:
|
113
|
+
c.stub(:shared_server_configs => { :foo => proc { call_from_foo }, :bar => proc { call_from_bar } })
|
114
|
+
c.should_receive(:call_from_foo)
|
115
|
+
c.should_receive(:call_from_bar)
|
90
116
|
c.include_shared_server_config(:foo, :bar)
|
91
117
|
end
|
92
118
|
end
|
93
119
|
|
94
|
-
context "when the
|
120
|
+
context "when the argument is hash where shared config names are keys" do
|
95
121
|
context "when hash values are arrays" do
|
96
122
|
it "includes config corresponding to hash key and passes exploded arguments" do
|
97
123
|
dsl(scopes[:server], factory.create(:server)) do |c|
|
@@ -113,6 +139,17 @@ describe "DSL" do
|
|
113
139
|
end
|
114
140
|
end
|
115
141
|
|
142
|
+
context "whne there are symbol arguments (names of shared configs) and a hash" do
|
143
|
+
it "includes config corresponding to symbol arguments and hash keys" do
|
144
|
+
dsl(scopes[:server], factory.create(:server)) do |c|
|
145
|
+
c.stub(:shared_server_configs => { :foo => proc { call_from_foo }, :bar => proc { |qux| call_from_bar(qux) } })
|
146
|
+
c.should_receive(:call_from_foo)
|
147
|
+
c.should_receive(:call_from_bar).with(123)
|
148
|
+
c.include_shared_server_config(:foo, :bar => 123)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
116
153
|
it "raises ConfigError if non-existent config included" do
|
117
154
|
dsl(scopes[:server], factory.create(:server)) do |c|
|
118
155
|
expect { c.include_shared_server_config(:foo) }.to raise_error(Taketo::DSL::ConfigError, "Shared server config 'foo' is not defined!")
|
@@ -131,6 +168,20 @@ describe "DSL" do
|
|
131
168
|
describe "#server" do
|
132
169
|
it_behaves_like "a scope", :server, :environment
|
133
170
|
|
171
|
+
it "evaluates default_server_config" do
|
172
|
+
dsl(scopes[:environment], factory.create(:environment, :foo)) do |c|
|
173
|
+
stub_find_or_create_scope_object(c, :server, :bar)
|
174
|
+
|
175
|
+
default_server_config = proc { some_setup }
|
176
|
+
factory.server.stub(:default_server_config => default_server_config)
|
177
|
+
|
178
|
+
c.should_receive(:some_setup)
|
179
|
+
|
180
|
+
c.server(:bar) do
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
134
185
|
it "has name optional" do
|
135
186
|
dsl(scopes[:environment], factory.create(:environment, :foo)) do |c|
|
136
187
|
stub_find_or_create_scope_object(c, :server, :default)
|
@@ -7,23 +7,23 @@ module DSLSpec
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def create_config(*args)
|
10
|
-
@config ||= RSpec::Mocks::Mock.new(:Config).as_null_object
|
10
|
+
@config ||= RSpec::Mocks::Mock.new(:Config, :default_server_config => proc {}).as_null_object
|
11
11
|
end
|
12
12
|
|
13
13
|
def create_project(name = :foo)
|
14
|
-
@project ||= RSpec::Mocks::Mock.new(:Project, :name => name).as_null_object
|
14
|
+
@project ||= RSpec::Mocks::Mock.new(:Project, :name => name, :default_server_config => proc {}).as_null_object
|
15
15
|
end
|
16
16
|
|
17
17
|
def create_environment(name = :foo)
|
18
|
-
@environment ||= RSpec::Mocks::Mock.new(:Environment, :name => name).as_null_object
|
18
|
+
@environment ||= RSpec::Mocks::Mock.new(:Environment, :name => name, :default_server_config => proc {}).as_null_object
|
19
19
|
end
|
20
20
|
|
21
21
|
def create_server(name = :foo)
|
22
|
-
@server ||= RSpec::Mocks::Mock.new(:Server, :name => name).as_null_object
|
22
|
+
@server ||= RSpec::Mocks::Mock.new(:Server, :name => name, :default_server_config => proc {}).as_null_object
|
23
23
|
end
|
24
24
|
|
25
25
|
def create_command(name = :the_cmd)
|
26
|
-
@command ||= RSpec::Mocks::Mock.new(:Command, :name => name).as_null_object
|
26
|
+
@command ||= RSpec::Mocks::Mock.new(:Command, :name => name, :default_server_config => proc {}).as_null_object
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
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.
|
4
|
+
version: 0.0.8
|
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-
|
12
|
+
date: 2012-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -138,6 +138,7 @@ files:
|
|
138
138
|
- features/config.feature
|
139
139
|
- features/config_validation.feature
|
140
140
|
- features/connect_to_server.feature
|
141
|
+
- features/default_server_config.feature
|
141
142
|
- features/error_handling.feature
|
142
143
|
- features/help.feature
|
143
144
|
- features/step_definitions/main_steps.rb
|