taketo 0.0.2 → 0.0.3
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 +48 -3
- data/VERSION +1 -1
- data/bin/taketo +5 -3
- data/features/commands.feature +2 -2
- data/features/connect_to_server.feature +46 -1
- data/lib/taketo/constructs/base_construct.rb +24 -0
- data/lib/taketo/constructs/command.rb +3 -7
- data/lib/taketo/constructs/config.rb +7 -1
- data/lib/taketo/constructs/environment.rb +8 -3
- data/lib/taketo/constructs/project.rb +8 -3
- data/lib/taketo/constructs/server.rb +11 -14
- data/lib/taketo/destination_resolver.rb +118 -0
- data/lib/taketo/dsl.rb +9 -8
- data/lib/taketo/support/named_nodes_collection.rb +11 -2
- data/spec/integration/dsl_integration_spec.rb +7 -0
- data/spec/lib/taketo/constructs/base_construct_spec.rb +45 -0
- data/spec/lib/taketo/constructs/config_spec.rb +13 -0
- data/spec/lib/taketo/constructs/environment_spec.rb +7 -0
- data/spec/lib/taketo/constructs/project_spec.rb +7 -0
- data/spec/lib/taketo/constructs/server_spec.rb +4 -16
- data/spec/lib/taketo/constructs_factory_spec.rb +1 -1
- data/spec/lib/taketo/destination_resolver_spec.rb +170 -0
- data/spec/lib/taketo/dsl_spec.rb +39 -27
- data/spec/lib/taketo/support/eval_delegator_spec.rb +7 -1
- data/spec/lib/taketo/support/named_nodes_collection_spec.rb +7 -0
- data/spec/support/helpers/dsl_spec_helper.rb +1 -1
- metadata +6 -4
- data/lib/taketo/taketo_argv_parser.rb +0 -48
- data/spec/lib/taketo/taketo_argv_parser_spec.rb +0 -92
data/README.md
CHANGED
@@ -4,7 +4,15 @@ Take Me To
|
|
4
4
|
[](http://travis-ci.org/v-yarotsky/taketo)
|
5
5
|
[](https://codeclimate.com/github/v-yarotsky/taketo)
|
6
6
|
|
7
|
-
A tiny helper utility to make access to servers
|
7
|
+
A tiny helper utility to make access to servers easier for different projects and environments.
|
8
|
+
|
9
|
+
Important note:
|
10
|
+
---------------
|
11
|
+
|
12
|
+
The project is currently actively developed, thus it may contain bugs;
|
13
|
+
backward compatibility is not guaranteed.
|
14
|
+
|
15
|
+
Suggestions and contributions are highly appreciated :)
|
8
16
|
|
9
17
|
Usage:
|
10
18
|
------
|
@@ -28,9 +36,42 @@ puts a config into ```~/.taketo.rc.rb```:
|
|
28
36
|
end
|
29
37
|
```
|
30
38
|
|
31
|
-
Then execute ```taketo my_project
|
32
|
-
or just ```taketo my_project
|
39
|
+
Then execute ```taketo my_project:staging:server -c console``` to execute the "rails c" with corresponding environment variables set on desired server
|
40
|
+
or just ```taketo my_project:staging:server``` to open bash
|
41
|
+
|
42
|
+
Destination resolving works intelligently. Given the following config:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
default_destination "my_project2:staging:s2"
|
33
46
|
|
47
|
+
project :my_project do
|
48
|
+
environment :staging do
|
49
|
+
server :s1 do
|
50
|
+
host "1.2.3.4"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
environment :production do
|
54
|
+
server :ps1 do
|
55
|
+
host "3.4.5.6"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
project :my_project2 do
|
61
|
+
environment :staging do
|
62
|
+
server :s2 do
|
63
|
+
host "2.3.4.5"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
```taketo my_project:staging``` will ssh to s1 with host = 1.2.3.4
|
70
|
+
```taketo my_project2``` will ssh to s2 with host = 2.3.4.5
|
71
|
+
|
72
|
+
Note that default destination can be specified via ```default_destination``` config option
|
73
|
+
|
74
|
+
|
34
75
|
To-Do:
|
35
76
|
------
|
36
77
|
|
@@ -40,6 +81,10 @@ To-Do:
|
|
40
81
|
The Changelog:
|
41
82
|
--------------
|
42
83
|
|
84
|
+
### v0.0.3 (22.07.2012) ###
|
85
|
+
* Add default_destination config option
|
86
|
+
* Add intelligent destination resolving
|
87
|
+
|
43
88
|
### v0.0.2 (21.07.2012) ###
|
44
89
|
* Add ability to define environment variables
|
45
90
|
* Add support for server commands
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/bin/taketo
CHANGED
@@ -6,7 +6,7 @@ begin
|
|
6
6
|
require 'taketo'
|
7
7
|
require 'taketo/constructs_factory'
|
8
8
|
require 'taketo/commands'
|
9
|
-
require 'taketo/
|
9
|
+
require 'taketo/destination_resolver'
|
10
10
|
require 'optparse'
|
11
11
|
rescue LoadError => e #development
|
12
12
|
raise if $loaded
|
@@ -62,7 +62,7 @@ end
|
|
62
62
|
|
63
63
|
def remote_command(server, options)
|
64
64
|
command_name = options[:command] or return default_command(options)
|
65
|
-
server.
|
65
|
+
server.find(:command, command_name.to_sym) { default_command(options) }
|
66
66
|
end
|
67
67
|
|
68
68
|
def default_command(options)
|
@@ -75,7 +75,8 @@ begin
|
|
75
75
|
options = parse_options
|
76
76
|
config = parse_config(options[:config])
|
77
77
|
|
78
|
-
|
78
|
+
destination_path = ARGV.shift.to_s
|
79
|
+
server = DestinationResolver.new(config, destination_path).resolve
|
79
80
|
|
80
81
|
server_command = remote_command(server, options)
|
81
82
|
command_to_execute = Commands::SSHCommand.new(server).render(server_command)
|
@@ -91,3 +92,4 @@ rescue Exception => e
|
|
91
92
|
STDERR.puts "An error occurred: #{e.message}"
|
92
93
|
raise if options && options[:debug]
|
93
94
|
end
|
95
|
+
|
data/features/commands.feature
CHANGED
@@ -16,7 +16,7 @@ Feature:
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
"""
|
19
|
-
|
19
|
+
And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run --command "TERM=xterm-256color bash"`
|
20
20
|
Then the output should contain
|
21
21
|
"""
|
22
22
|
ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging TERM=xterm-256color bash"
|
@@ -37,7 +37,7 @@ Feature:
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
"""
|
40
|
-
|
40
|
+
And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run --command console slots:staging:s1`
|
41
41
|
Then the output should contain
|
42
42
|
"""
|
43
43
|
ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging rails c"
|
@@ -14,11 +14,15 @@ Feature:
|
|
14
14
|
user "deployer"
|
15
15
|
location "/var/apps/slots"
|
16
16
|
end
|
17
|
+
|
18
|
+
server :s2 do
|
19
|
+
host "2.3.4.5"
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
20
24
|
"""
|
21
|
-
And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run slots
|
25
|
+
And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run slots:staging:s1`
|
22
26
|
Then the output should contain
|
23
27
|
"""
|
24
28
|
ssh -t deployer@1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging bash"
|
@@ -65,3 +69,44 @@ Feature:
|
|
65
69
|
FOO=the\ value
|
66
70
|
"""
|
67
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 :s1 do
|
78
|
+
host "1.2.3.4"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
project :slots do
|
84
|
+
environment :staging do
|
85
|
+
server :s1 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:s1 --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
|
+
Scenario: Default destination
|
95
|
+
When I have the following config in "/tmp/taketo_test_cfg.rb"
|
96
|
+
"""
|
97
|
+
default_destination "slots:staging:s2"
|
98
|
+
project :slots do
|
99
|
+
environment :staging do
|
100
|
+
server :s1 do
|
101
|
+
end
|
102
|
+
server :s2 do
|
103
|
+
host "2.3.4.5"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
"""
|
108
|
+
And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run`
|
109
|
+
Then the output should contain
|
110
|
+
"""
|
111
|
+
ssh -t 2.3.4.5 "RAILS_ENV=staging bash"
|
112
|
+
"""
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'taketo/support'
|
2
|
+
|
3
|
+
module Taketo
|
4
|
+
module Constructs
|
5
|
+
class BaseConstruct
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(scope, name)
|
13
|
+
send("find_#{scope}", name) or
|
14
|
+
if block_given?
|
15
|
+
yield
|
16
|
+
else
|
17
|
+
raise KeyError, "#{scope.to_s.capitalize} #{name} not found for #{self.class.name} #{name}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
@@ -1,19 +1,15 @@
|
|
1
|
+
require 'taketo/constructs/base_construct'
|
1
2
|
require 'shellwords'
|
2
3
|
|
3
4
|
module Taketo
|
4
5
|
module Constructs
|
5
|
-
class Command
|
6
|
+
class Command < BaseConstruct
|
6
7
|
include Shellwords
|
7
8
|
|
8
|
-
attr_reader :name
|
9
9
|
attr_accessor :command
|
10
10
|
|
11
|
-
def initialize(name)
|
12
|
-
@name = name
|
13
|
-
end
|
14
|
-
|
15
11
|
def render(server)
|
16
|
-
%Q[#{location(server)} #{environment_variables(server)} #{command}].squeeze(" ")
|
12
|
+
%Q[#{location(server)} #{environment_variables(server)} #{command}].strip.squeeze(" ")
|
17
13
|
end
|
18
14
|
|
19
15
|
private
|
@@ -1,9 +1,11 @@
|
|
1
|
+
require 'taketo/constructs/base_construct'
|
1
2
|
require 'taketo/support'
|
2
3
|
|
3
4
|
module Taketo
|
4
5
|
module Constructs
|
5
|
-
class Config
|
6
|
+
class Config < BaseConstruct
|
6
7
|
attr_reader :projects
|
8
|
+
attr_accessor :default_destination
|
7
9
|
|
8
10
|
def initialize
|
9
11
|
@projects = Taketo::Support::NamedNodesCollection.new
|
@@ -12,6 +14,10 @@ module Taketo
|
|
12
14
|
def append_project(project)
|
13
15
|
@projects << project
|
14
16
|
end
|
17
|
+
|
18
|
+
def find_project(name)
|
19
|
+
@projects.find_by_name(name)
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
@@ -1,12 +1,13 @@
|
|
1
|
+
require 'taketo/constructs/base_construct'
|
1
2
|
require 'taketo/support'
|
2
3
|
|
3
4
|
module Taketo
|
4
5
|
module Constructs
|
5
|
-
class Environment
|
6
|
-
attr_reader :
|
6
|
+
class Environment < BaseConstruct
|
7
|
+
attr_reader :servers
|
7
8
|
|
8
9
|
def initialize(name)
|
9
|
-
|
10
|
+
super
|
10
11
|
@servers = Taketo::Support::NamedNodesCollection.new
|
11
12
|
end
|
12
13
|
|
@@ -14,6 +15,10 @@ module Taketo
|
|
14
15
|
server.environment = self
|
15
16
|
@servers << server
|
16
17
|
end
|
18
|
+
|
19
|
+
def find_server(name)
|
20
|
+
@servers.find_by_name(name)
|
21
|
+
end
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
@@ -1,18 +1,23 @@
|
|
1
|
+
require 'taketo/constructs/base_construct'
|
1
2
|
require 'taketo/support'
|
2
3
|
|
3
4
|
module Taketo
|
4
5
|
module Constructs
|
5
|
-
class Project
|
6
|
-
attr_reader :
|
6
|
+
class Project < BaseConstruct
|
7
|
+
attr_reader :environments
|
7
8
|
|
8
9
|
def initialize(name)
|
9
|
-
|
10
|
+
super
|
10
11
|
@environments = Taketo::Support::NamedNodesCollection.new
|
11
12
|
end
|
12
13
|
|
13
14
|
def append_environment(environment)
|
14
15
|
@environments << environment
|
15
16
|
end
|
17
|
+
|
18
|
+
def find_environment(name)
|
19
|
+
@environments.find_by_name(name)
|
20
|
+
end
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
+
require 'taketo/constructs/base_construct'
|
2
|
+
require 'taketo/support'
|
3
|
+
|
1
4
|
module Taketo
|
2
5
|
module Constructs
|
3
|
-
class Server
|
6
|
+
class Server < BaseConstruct
|
4
7
|
class CommandNotFoundError < StandardError; end
|
5
8
|
|
6
|
-
attr_reader :
|
9
|
+
attr_reader :environment_variables, :commands
|
7
10
|
attr_accessor :host, :port, :username, :default_location, :environment
|
8
11
|
|
9
12
|
def initialize(name)
|
10
|
-
|
13
|
+
super
|
11
14
|
@environment_variables = {}
|
12
|
-
@commands =
|
15
|
+
@commands = Taketo::Support::NamedNodesCollection.new
|
13
16
|
end
|
14
17
|
|
15
18
|
def env(env_variables)
|
@@ -20,20 +23,14 @@ module Taketo
|
|
20
23
|
@commands << command
|
21
24
|
end
|
22
25
|
|
26
|
+
def find_command(name)
|
27
|
+
@commands.find_by_name(name)
|
28
|
+
end
|
29
|
+
|
23
30
|
def environment=(environment)
|
24
31
|
env(:RAILS_ENV => environment.name.to_s)
|
25
32
|
@environment = environment
|
26
33
|
end
|
27
|
-
|
28
|
-
def command_by_name(command_name)
|
29
|
-
@commands.detect { |c| c.name == command_name } or
|
30
|
-
if block_given?
|
31
|
-
yield
|
32
|
-
else
|
33
|
-
raise CommandNotFoundError, "Command #{command_name} not found for server #{name}"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
34
|
end
|
38
35
|
end
|
39
36
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Taketo
|
2
|
+
class ConfigError < StandardError; end
|
3
|
+
class AmbiguousDestinationError < StandardError; end
|
4
|
+
class NonExistentDestinationError < StandardError; end
|
5
|
+
|
6
|
+
class DestinationResolver
|
7
|
+
def initialize(config, path)
|
8
|
+
@config = config
|
9
|
+
set_destination(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def resolve
|
13
|
+
case @path.size
|
14
|
+
when 3 then resolve_by_three_segments
|
15
|
+
when 2 then resolve_by_two_segments
|
16
|
+
when 1 then resolve_by_one_segment
|
17
|
+
when 0 then resolve_with_no_segments
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def set_destination(path)
|
24
|
+
@path_str = path
|
25
|
+
@path = String(path).split(":").map(&:to_sym)
|
26
|
+
end
|
27
|
+
|
28
|
+
def resolve_by_three_segments
|
29
|
+
get_server(*@path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolve_by_two_segments
|
33
|
+
project, environment = get_project_and_environment(*@path)
|
34
|
+
get_only_server_for_project_and_environment(project, environment)
|
35
|
+
end
|
36
|
+
|
37
|
+
def resolve_by_one_segment
|
38
|
+
project = get_project(*@path)
|
39
|
+
get_only_server_for_project(project)
|
40
|
+
end
|
41
|
+
|
42
|
+
def resolve_with_no_segments
|
43
|
+
unless @config.default_destination.nil?
|
44
|
+
set_destination(@config.default_destination.to_s)
|
45
|
+
return resolve
|
46
|
+
end
|
47
|
+
get_only_server
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_server(project_name, environment_name, server_name)
|
51
|
+
handling_failure("There is no such project, environment or server for destination: #@path_str") do
|
52
|
+
project, environment = get_project_and_environment(project_name, environment_name)
|
53
|
+
environment.servers[server_name]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_project_and_environment(project_name, environment_name)
|
58
|
+
handling_failure("There is no such project - environment pair: #@path_str") do
|
59
|
+
project = get_project(project_name)
|
60
|
+
environment = project.environments[environment_name]
|
61
|
+
[project, environment]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_only_server_for_project_and_environment(project, environment)
|
66
|
+
if environment.servers.one?
|
67
|
+
return environment.servers.first
|
68
|
+
else
|
69
|
+
raise_server_ambiguous!(project, environment)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_project(project_name)
|
74
|
+
handling_failure("There is no such project: #@path_str") do
|
75
|
+
@config.projects[project_name]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_only_server_for_project(project)
|
80
|
+
if project.environments.one?
|
81
|
+
environment = project.environments.first
|
82
|
+
get_only_server_for_project_and_environment(project, environment)
|
83
|
+
else
|
84
|
+
raise_environment_ambiguous!(project)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_only_server
|
89
|
+
if @config.projects.one?
|
90
|
+
project = @config.projects.first
|
91
|
+
get_only_server_for_project(project)
|
92
|
+
else
|
93
|
+
raise_project_ambiguous!
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def raise_project_ambiguous!
|
98
|
+
raise AmbiguousDestinationError, "There are multiple projects #{@config.projects.map(&:name).join(", ")}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def raise_environment_ambiguous!(project)
|
102
|
+
raise AmbiguousDestinationError, "There are multiple environments for project #{project.name}: " \
|
103
|
+
"#{project.environments.map(&:name).join(", ")}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def raise_server_ambiguous!(project, environment)
|
107
|
+
raise AmbiguousDestinationError, "There are multiple servers for project #{project.name} " \
|
108
|
+
"in environment #{environment.name}: #{environment.servers.map(&:name).join(", ")}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def handling_failure(message)
|
112
|
+
yield
|
113
|
+
rescue KeyError, NonExistentDestinationError
|
114
|
+
raise NonExistentDestinationError, message
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
data/lib/taketo/dsl.rb
CHANGED
@@ -11,7 +11,7 @@ module Taketo
|
|
11
11
|
raise ScopeError,
|
12
12
|
"#{scope} can't be defined in #{current_scope} scope"
|
13
13
|
end
|
14
|
-
scope_object = @factory.create(scope, name)
|
14
|
+
scope_object = current_scope_object.find(scope, name) { @factory.create(scope, name) }
|
15
15
|
in_scope(scope, scope_object) do
|
16
16
|
block.call
|
17
17
|
end
|
@@ -55,12 +55,13 @@ module Taketo
|
|
55
55
|
define_scope :server, :environment
|
56
56
|
define_scope :command, :server
|
57
57
|
|
58
|
-
define_attribute(:
|
59
|
-
define_attribute(:
|
60
|
-
define_attribute(:
|
61
|
-
define_attribute(:
|
62
|
-
define_attribute(:
|
63
|
-
define_attribute(:
|
58
|
+
define_attribute(:default_destination, :config) { |destination| current_scope_object.default_destination = destination }
|
59
|
+
define_attribute(:host, :server) { |hostname| current_scope_object.host = hostname }
|
60
|
+
define_attribute(:port, :server) { |port_number| current_scope_object.port = port_number }
|
61
|
+
define_attribute(:user, :server) { |username| current_scope_object.username = username }
|
62
|
+
define_attribute(:location, :server) { |path| current_scope_object.default_location = path }
|
63
|
+
define_attribute(:env, :server) { |env| current_scope_object.env(env) }
|
64
|
+
define_attribute(:execute, :command) { |command| current_scope_object.command = command }
|
64
65
|
|
65
66
|
private
|
66
67
|
|
@@ -78,7 +79,7 @@ module Taketo
|
|
78
79
|
|
79
80
|
def in_scope(scope, new_scope_object)
|
80
81
|
parent_scope_object, @current_scope_object = @current_scope_object, new_scope_object
|
81
|
-
@scope
|
82
|
+
@scope.push(scope)
|
82
83
|
yield
|
83
84
|
parent_scope_object.send("append_#{scope}", current_scope_object)
|
84
85
|
@scope.pop
|
@@ -7,19 +7,28 @@ module Taketo
|
|
7
7
|
include Enumerable
|
8
8
|
extend Forwardable
|
9
9
|
|
10
|
-
def_delegators :@nodes, :each,
|
10
|
+
def_delegators :@nodes, :each, :length, :size, :empty?
|
11
11
|
|
12
12
|
def initialize(nodes = [])
|
13
13
|
@nodes = nodes
|
14
14
|
end
|
15
15
|
|
16
|
+
def push(node)
|
17
|
+
@nodes << node unless find_by_name(node.name)
|
18
|
+
end
|
19
|
+
alias :<< :push
|
20
|
+
|
16
21
|
def [](index)
|
17
22
|
if index.is_a?(Symbol)
|
18
|
-
node =
|
23
|
+
node = find_by_name(index) or raise KeyError, "Element with name #{index} not found"
|
19
24
|
return node
|
20
25
|
end
|
21
26
|
@nodes[index] or raise KeyError, "Element ##{index} not found"
|
22
27
|
end
|
28
|
+
|
29
|
+
def find_by_name(name)
|
30
|
+
@nodes.detect { |n| n.name == name }
|
31
|
+
end
|
23
32
|
end
|
24
33
|
end
|
25
34
|
end
|
@@ -11,6 +11,10 @@ describe "Taketo DSL" do
|
|
11
11
|
host "127.0.0.2"
|
12
12
|
user "deployer"
|
13
13
|
location "/var/app"
|
14
|
+
env :FOO => "bar"
|
15
|
+
command :console do
|
16
|
+
execute "rails c"
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
@@ -40,6 +44,9 @@ describe "Taketo DSL" do
|
|
40
44
|
staging_server.host.should == "127.0.0.2"
|
41
45
|
staging_server.username.should == "deployer"
|
42
46
|
staging_server.default_location.should == "/var/app"
|
47
|
+
staging_server.environment_variables.should == { :RAILS_ENV => "staging", :FOO => "bar" }
|
48
|
+
staging_server.commands.length.should == 1
|
49
|
+
staging_server.commands[:console].command.should == "rails c"
|
43
50
|
|
44
51
|
production = project.environments[:production]
|
45
52
|
production.servers.length.should == 2
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path('../../../../spec_helper', __FILE__)
|
2
|
+
require 'taketo/constructs/base_construct'
|
3
|
+
|
4
|
+
include Taketo
|
5
|
+
|
6
|
+
describe "BaseConstruct" do
|
7
|
+
class TestConstruct < Constructs::BaseConstruct
|
8
|
+
attr_reader :foos
|
9
|
+
|
10
|
+
def initialize(name, foos)
|
11
|
+
super(name)
|
12
|
+
@foos = foos
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_foo(name)
|
16
|
+
@foos[name]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:foos) { mock(:NamedNodesCollection) }
|
21
|
+
let(:construct) { TestConstruct.new(:construct, foos) }
|
22
|
+
|
23
|
+
describe "#find" do
|
24
|
+
context "if there is such node" do
|
25
|
+
it "should return node object with corresponding name" do
|
26
|
+
foos.should_receive(:[]).with(:bar).and_return(:qux)
|
27
|
+
construct.find(:foo, :bar).should == :qux
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "if there is no such command" do
|
32
|
+
before(:each) { foos.should_receive(:[]).and_return(nil) }
|
33
|
+
|
34
|
+
it "should yield if block given" do
|
35
|
+
expect { |b| construct.find(:foo, :bar, &b) }.to yield_control
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should raise KeyError if no block given" do
|
39
|
+
expect { construct.find(:foo, :bar) }.to raise_error(KeyError)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
@@ -13,5 +13,18 @@ describe "Config" do
|
|
13
13
|
config.projects.should include(project)
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
describe "#find_project" do
|
18
|
+
it "should find project by name" do
|
19
|
+
config.projects.should_receive(:find_by_name).with(:foo).and_return(:bar)
|
20
|
+
config.find_project(:foo).should == :bar
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set default_destination" do
|
25
|
+
config.default_destination.should be_nil
|
26
|
+
config.default_destination = "foo:bar:baz"
|
27
|
+
config.default_destination.should == "foo:bar:baz"
|
28
|
+
end
|
16
29
|
end
|
17
30
|
|
@@ -23,6 +23,13 @@ describe "Environment" do
|
|
23
23
|
environment.append_server(server)
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
describe "#find_server" do
|
28
|
+
it "should find server by name" do
|
29
|
+
environment.servers.should_receive(:find_by_name).with(:foo).and_return(:bar)
|
30
|
+
environment.find_server(:foo).should == :bar
|
31
|
+
end
|
32
|
+
end
|
26
33
|
end
|
27
34
|
|
28
35
|
|
@@ -17,5 +17,12 @@ describe "Project" do
|
|
17
17
|
project.environments.should include(environment)
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
describe "#find_environment" do
|
22
|
+
it "should find environment by name" do
|
23
|
+
project.environments.should_receive(:find_by_name).with(:foo).and_return(:bar)
|
24
|
+
project.find_environment(:foo).should == :bar
|
25
|
+
end
|
26
|
+
end
|
20
27
|
end
|
21
28
|
|
@@ -60,22 +60,10 @@ describe "Server" do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
describe "#
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
server.command_by_name(:foo).should == command
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
context "if there is no such command" do
|
72
|
-
it "should yield if block given" do
|
73
|
-
expect { |b| server.command_by_name(:bar, &b) }.to yield_control
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should raise CommandNotFoundError if no block given" do
|
77
|
-
expect { server.command_by_name(:bar) }.to raise_error(Taketo::Constructs::Server::CommandNotFoundError)
|
78
|
-
end
|
63
|
+
describe "#find_command" do
|
64
|
+
it "should find command by name" do
|
65
|
+
server.commands.should_receive(:find_by_name).with(:foo).and_return(:bar)
|
66
|
+
server.find_command(:foo).should == :bar
|
79
67
|
end
|
80
68
|
end
|
81
69
|
end
|
@@ -6,7 +6,7 @@ include Taketo
|
|
6
6
|
describe "ConstructsFactory" do
|
7
7
|
let(:factory) { Taketo::ConstructsFactory.new }
|
8
8
|
|
9
|
-
specify "#create should delegate to
|
9
|
+
specify "#create should delegate to appropriate method according to the type" do
|
10
10
|
factory.should_receive(:create_config)
|
11
11
|
factory.create(:config)
|
12
12
|
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require 'taketo/destination_resolver'
|
3
|
+
require 'taketo/support/named_nodes_collection'
|
4
|
+
|
5
|
+
include Taketo
|
6
|
+
|
7
|
+
describe "DestinationResolver" do
|
8
|
+
let(:server1) { stub(:Server, :name => :s1) }
|
9
|
+
let(:server2) { stub(:Server, :name => :s2) }
|
10
|
+
let(:server3) { stub(:Server, :name => :s3) }
|
11
|
+
let(:server4) { stub(:Server, :name => :s4) }
|
12
|
+
let(:config) do
|
13
|
+
stub(:Config, :projects => list(
|
14
|
+
stub(:name => :foo, :environments => list(
|
15
|
+
stub(:name => :bar, :servers => list(server1))
|
16
|
+
)),
|
17
|
+
stub(:name => :baz, :environments => list(
|
18
|
+
stub(:name => :qux, :servers => list(server2))
|
19
|
+
)),
|
20
|
+
stub(:name => :quux, :environments => list(
|
21
|
+
stub(:name => :corge, :servers => list(server3, server4))
|
22
|
+
)),
|
23
|
+
stub(:name => :grault, :environments => list(
|
24
|
+
stub(:name => :garply, :servers => list(anything, anything)),
|
25
|
+
stub(:name => :waldo, :servers => list(anything))
|
26
|
+
))
|
27
|
+
))
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when project, environment and server specified" do
|
31
|
+
it "should return server if it exists" do
|
32
|
+
resolver(config, "foo:bar:s1").resolve.should == server1
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should raise error if server does not exist" do
|
36
|
+
config = stub(:Config, :projects => list())
|
37
|
+
expect { resolver(config, "foo:bar:noserver").resolve }.to raise_error(NonExistentDestinationError, /no such/i)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when there are 2 segments in path" do
|
42
|
+
context "when there is matching project - environment pair" do
|
43
|
+
it "should return server if only one specified" do
|
44
|
+
resolver(config, "foo:bar").resolve.should == server1
|
45
|
+
resolver(config, "baz:qux").resolve.should == server2
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should raise error if there are multiple servers" do
|
49
|
+
expect { resolver(config, "quux:corge").resolve }.to raise_error(AmbiguousDestinationError, /servers/i)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when there is no matching project - environment pair" do
|
54
|
+
it "should raise error if no such project - environment pair exist" do
|
55
|
+
expect { resolver(config, "chunky:bacon").resolve }.to raise_error(NonExistentDestinationError, /project.*environment/i)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when there is only one segment in the path" do
|
61
|
+
context "when project with given name exists" do
|
62
|
+
context "when there's one environment" do
|
63
|
+
context "when there's one server" do
|
64
|
+
it "should return the server" do
|
65
|
+
resolver(config, "foo").resolve.should == server1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when there are multiple servers" do
|
70
|
+
it "should raise error" do
|
71
|
+
expect { resolver(config, "quux").resolve }.to raise_error(AmbiguousDestinationError, /servers/i)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when there are multiple environments" do
|
77
|
+
it "should raise error" do
|
78
|
+
expect { resolver(config, "grault").resolve }.to raise_error(AmbiguousDestinationError, /environments/i)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when there is no such project" do
|
84
|
+
it "should raise error" do
|
85
|
+
expect { resolver(config, "chunky").resolve }.to raise_error(NonExistentDestinationError, /project/i)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when passed path is empty" do
|
91
|
+
context "when there is no default destination set" do
|
92
|
+
context "when there's one project" do
|
93
|
+
context "when there's one environment" do
|
94
|
+
context "when there's one server" do
|
95
|
+
it "should execute command without asking project/environment/server" do
|
96
|
+
config = stub(:Config, :default_destination => nil, :projects => list(
|
97
|
+
stub(:name => :foo, :environments => list(
|
98
|
+
stub(:name => :bar, :servers => list(
|
99
|
+
server1
|
100
|
+
))
|
101
|
+
))
|
102
|
+
))
|
103
|
+
|
104
|
+
resolver(config, "").resolve.should == server1
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "when there are multiple servers" do
|
109
|
+
let(:server1) { stub(:Server, :name => :s1) }
|
110
|
+
let(:server2) { stub(:Server, :name => :s2) }
|
111
|
+
|
112
|
+
it "should ask for server" do
|
113
|
+
config = stub(:Config, :default_destination => nil, :projects => list(
|
114
|
+
stub(:name => :foo, :environments => list(
|
115
|
+
stub(:name => :bar, :servers => list(
|
116
|
+
server1, server2
|
117
|
+
))
|
118
|
+
))
|
119
|
+
))
|
120
|
+
|
121
|
+
expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /server/i
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when there are multiple environments" do
|
127
|
+
it "should ask for environment" do
|
128
|
+
config = stub(:Config, :default_destination => nil, :projects => list(
|
129
|
+
stub(:name => :foo, :environments => list(
|
130
|
+
stub(:name => :bar, :servers => [anything]),
|
131
|
+
stub(:name => :baz, :servers => [anything])
|
132
|
+
))
|
133
|
+
))
|
134
|
+
|
135
|
+
expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /environment/i
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "when there are multiple projects" do
|
141
|
+
it "should ask for project" do
|
142
|
+
config = stub(:Config, :default_destination => nil, :projects => list(
|
143
|
+
stub(:name => :foo, :environments => [anything]),
|
144
|
+
stub(:name => :bar, :environments => [anything])
|
145
|
+
))
|
146
|
+
|
147
|
+
expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /projects/i
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "when there is default destination" do
|
153
|
+
it "should resolve by default destination" do
|
154
|
+
config.stub(:default_destination => "foo:bar:s1")
|
155
|
+
resolver(config, "").resolve.should == server1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
def resolver(*args)
|
162
|
+
DestinationResolver.new(*args)
|
163
|
+
end
|
164
|
+
|
165
|
+
def list(*items)
|
166
|
+
Taketo::Support::NamedNodesCollection.new(items)
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
data/spec/lib/taketo/dsl_spec.rb
CHANGED
@@ -18,28 +18,36 @@ describe "DSL" do
|
|
18
18
|
it { should_not be_appropriate_construct(scope_name, :foo).under(inappropriate_scope) }
|
19
19
|
end
|
20
20
|
|
21
|
-
it "should create a #{scope_name} and set it as current scope object" do
|
22
|
-
dsl(parent_scope, factory.create(parent_scope_name)) do |c|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
c.current_scope_object.
|
40
|
-
|
41
|
-
|
42
|
-
|
21
|
+
it "should create a #{scope_name} and set it as current scope object" do # it "should create project and set it as current scope object"
|
22
|
+
dsl(parent_scope, factory.create(parent_scope_name)) do |c| # dsl([:config], factory.create(:config)) do |c|
|
23
|
+
c.current_scope_object.should_receive(:find).with(scope_name, :bar). # c.current_scope_object.should_receive(:find).with(:project, :bar).
|
24
|
+
and_yield.and_return(:bacon) # and_yield.and_return(:bacon)
|
25
|
+
factory.should_receive(:create).with(scope_name, :bar) # factory.should_receive(:create).with(:project, :bar)
|
26
|
+
c.send(scope_name, :bar) do # c.project(:bar) do
|
27
|
+
c.current_scope_object.should_not be_nil # c.current_scope_object.should_not be_nil
|
28
|
+
c.current_scope_object.should == :bacon # c.current_scope_object.should == factory.project
|
29
|
+
end # end
|
30
|
+
end # end
|
31
|
+
end # end
|
32
|
+
|
33
|
+
it "should not leak #{scope_name} as current scope object" do # it "should not leak project as current scope object"
|
34
|
+
dsl(parent_scope, factory.create(parent_scope_name)) do |c| # dsl([:config], factory.create(:config)) do |c|
|
35
|
+
c.current_scope_object.stub(:find => factory.create(scope_name, :bar)) # c.current_scope.stub(:find => factory.create(:project, :bar))
|
36
|
+
c.send(scope_name, :bar) do # c.project(:bar) do
|
37
|
+
c.current_scope_object.should == factory.send(scope_name) # c.current_scope_object.should == factory.project
|
38
|
+
end # end
|
39
|
+
c.current_scope_object.should_not == factory.send(scope_name) # c.current_scope_object.should_not == factory.project
|
40
|
+
end # end
|
41
|
+
end # end
|
42
|
+
|
43
|
+
it "should add a #{scope_name} to the #{parent_scope_name}'s #{scope_name}s collection" do # it "should add a project to the config's projects collection" do
|
44
|
+
dsl(parent_scope, factory.create(parent_scope_name)) do |c| # dsl([:config], factory.create(:config)) do |c|
|
45
|
+
c.current_scope_object.stub(:find => factory.create(scope_name, :bar)) # c.current_scope_object.stub(:find => factory.create(:project, :bar))
|
46
|
+
c.current_scope_object.should_receive("append_#{scope_name}"). # c.current_scope_object.should_receive(:append_project).
|
47
|
+
with(factory.send(scope_name)) # with(factory.project)
|
48
|
+
c.send(scope_name, :bar) {} # c.project(:bar) {}
|
49
|
+
end # end
|
50
|
+
end # end
|
43
51
|
end
|
44
52
|
|
45
53
|
shared_examples "an attribute" do |attribute_name, parent_scope_name, parent_scope_method, example_value|
|
@@ -51,14 +59,18 @@ describe "DSL" do
|
|
51
59
|
it { should_not be_appropriate_construct(attribute_name, example_value).under(inaproppriate_scope) }
|
52
60
|
end
|
53
61
|
|
54
|
-
it "should call #{parent_scope_method} on current #{parent_scope_name}" do
|
55
|
-
dsl(parent_scope, factory.create(parent_scope_name, :foo)) do |c|
|
56
|
-
factory.send(parent_scope_name).should_receive(parent_scope_method).with(example_value)
|
57
|
-
c.send(attribute_name, example_value)
|
58
|
-
end
|
62
|
+
it "should call #{parent_scope_method} on current #{parent_scope_name}" do # it "should call default_location= on current server" do
|
63
|
+
dsl(parent_scope, factory.create(parent_scope_name, :foo)) do |c| # dsl([:config, :project, :environment, :server], factory.create(:server, :foo)) do |c|
|
64
|
+
factory.send(parent_scope_name).should_receive(parent_scope_method).with(example_value) # factory.server.should_receive(:default_location=).with('/var/app/')
|
65
|
+
c.send(attribute_name, example_value) # c.location "/var/app"
|
66
|
+
end # end
|
59
67
|
end
|
60
68
|
end
|
61
69
|
|
70
|
+
describe "#default_destination" do
|
71
|
+
it_behaves_like "an attribute", :default_destination, :config, :default_destination=, "foo:bar:baz"
|
72
|
+
end
|
73
|
+
|
62
74
|
describe "#project" do
|
63
75
|
it_behaves_like "a scope", :project, :config
|
64
76
|
|
@@ -26,7 +26,13 @@ describe Taketo::Support::EvalDelegator do
|
|
26
26
|
end.not_to raise_error
|
27
27
|
end
|
28
28
|
|
29
|
-
it "should
|
29
|
+
it "should raise if external context does not respond" do
|
30
|
+
expect do
|
31
|
+
EvalDelegatorContext.new.evaluate { qux }
|
32
|
+
end.to raise_error(NameError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should pass local variabnes through the scopes" do
|
30
36
|
baz = :foo
|
31
37
|
expect do
|
32
38
|
EvalDelegatorContext.new.evaluate { baz }
|
@@ -24,6 +24,13 @@ describe "NamedNodesCollection" do
|
|
24
24
|
expect { collection[3] }.to raise_error KeyError, /#3/i
|
25
25
|
expect { collection[:quux] }.to raise_error KeyError, /name/i
|
26
26
|
end
|
27
|
+
|
28
|
+
it "should not add if node with same name exists" do
|
29
|
+
collection << node1
|
30
|
+
collection.push node1
|
31
|
+
collection.length.should == 1
|
32
|
+
collection.first.should == node1
|
33
|
+
end
|
27
34
|
end
|
28
35
|
|
29
36
|
|
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.3
|
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-
|
12
|
+
date: 2012-07-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -86,6 +86,7 @@ files:
|
|
86
86
|
- lib/taketo/commands/ssh_command.rb
|
87
87
|
- lib/taketo/commands.rb
|
88
88
|
- lib/taketo/config_validator.rb
|
89
|
+
- lib/taketo/constructs/base_construct.rb
|
89
90
|
- lib/taketo/constructs/command.rb
|
90
91
|
- lib/taketo/constructs/config.rb
|
91
92
|
- lib/taketo/constructs/environment.rb
|
@@ -93,26 +94,27 @@ files:
|
|
93
94
|
- lib/taketo/constructs/server.rb
|
94
95
|
- lib/taketo/constructs.rb
|
95
96
|
- lib/taketo/constructs_factory.rb
|
97
|
+
- lib/taketo/destination_resolver.rb
|
96
98
|
- lib/taketo/dsl.rb
|
97
99
|
- lib/taketo/support/eval_delegator.rb
|
98
100
|
- lib/taketo/support/key_error.rb
|
99
101
|
- lib/taketo/support/named_nodes_collection.rb
|
100
102
|
- lib/taketo/support.rb
|
101
|
-
- lib/taketo/taketo_argv_parser.rb
|
102
103
|
- lib/taketo.rb
|
103
104
|
- spec/integration/dsl_integration_spec.rb
|
104
105
|
- spec/lib/taketo/commands/ssh_command_spec.rb
|
105
106
|
- spec/lib/taketo/config_validator_spec.rb
|
107
|
+
- spec/lib/taketo/constructs/base_construct_spec.rb
|
106
108
|
- spec/lib/taketo/constructs/command_spec.rb
|
107
109
|
- spec/lib/taketo/constructs/config_spec.rb
|
108
110
|
- spec/lib/taketo/constructs/environment_spec.rb
|
109
111
|
- spec/lib/taketo/constructs/project_spec.rb
|
110
112
|
- spec/lib/taketo/constructs/server_spec.rb
|
111
113
|
- spec/lib/taketo/constructs_factory_spec.rb
|
114
|
+
- spec/lib/taketo/destination_resolver_spec.rb
|
112
115
|
- spec/lib/taketo/dsl_spec.rb
|
113
116
|
- spec/lib/taketo/support/eval_delegator_spec.rb
|
114
117
|
- spec/lib/taketo/support/named_nodes_collection_spec.rb
|
115
|
-
- spec/lib/taketo/taketo_argv_parser_spec.rb
|
116
118
|
- spec/spec_helper.rb
|
117
119
|
- spec/support/helpers/dsl_spec_helper.rb
|
118
120
|
- spec/support/matchers/be_appropriate_construct_matcher.rb
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module Taketo
|
2
|
-
class ConfigError < StandardError; end
|
3
|
-
|
4
|
-
class TaketoArgvParser
|
5
|
-
def initialize(config, argv)
|
6
|
-
@config = config
|
7
|
-
@argv = argv
|
8
|
-
end
|
9
|
-
|
10
|
-
def parse
|
11
|
-
if all_specified?
|
12
|
-
project_name, environment_name, server_name = @argv.shift(3).map(&:to_sym)
|
13
|
-
|
14
|
-
begin
|
15
|
-
return @config.projects[project_name].environments[environment_name].servers[server_name]
|
16
|
-
rescue KeyError
|
17
|
-
raise ArgumentError,
|
18
|
-
"Server #{server_name} in environment #{environment_name} for project #{project_name} does not exist"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
if @config.projects.one?
|
23
|
-
project = @config.projects.first
|
24
|
-
if project.environments.one?
|
25
|
-
environment = project.environments.first
|
26
|
-
if environment.servers.one?
|
27
|
-
return environment.servers.first
|
28
|
-
elsif environment.servers.length > 1
|
29
|
-
if server_name = @argv.shift
|
30
|
-
return environment.servers[server_name.to_sym]
|
31
|
-
else
|
32
|
-
raise ArgumentError, "There are multiple servers for project #{project.name} " \
|
33
|
-
"in environment #{environment.name}: #{environment.servers.map(&:name).join(", ")}"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def all_specified?
|
43
|
-
@argv.size >= 3
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
@@ -1,92 +0,0 @@
|
|
1
|
-
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
-
require 'taketo/taketo_argv_parser'
|
3
|
-
require 'taketo/support/named_nodes_collection'
|
4
|
-
|
5
|
-
include Taketo
|
6
|
-
|
7
|
-
describe "TaketoArgvParser" do
|
8
|
-
context "when project, environment and server specified" do
|
9
|
-
let(:server) { stub(:Server, :name => :baz) }
|
10
|
-
|
11
|
-
it "should return server if it exists" do
|
12
|
-
config = stub(:Config, :projects => list(
|
13
|
-
stub(:name => :foo, :environments => list(
|
14
|
-
stub(:name => :bar, :servers => list(
|
15
|
-
server
|
16
|
-
))
|
17
|
-
))
|
18
|
-
))
|
19
|
-
|
20
|
-
parser(config, %w(foo bar baz)).parse.should == server
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should raise error if server does not exist" do
|
24
|
-
config = stub(:Config, :projects => list())
|
25
|
-
expect do
|
26
|
-
parser(config, %w(foo bar baz)).parse
|
27
|
-
end.to raise_error ArgumentError, /exist/i
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context "when there are two arguments" do
|
32
|
-
end
|
33
|
-
|
34
|
-
context "when there are no args" do
|
35
|
-
context "when there's one project" do
|
36
|
-
context "when there's one environment" do
|
37
|
-
context "when there's one server" do
|
38
|
-
let(:server) { stub(:Server) }
|
39
|
-
|
40
|
-
it "should execute command without asking project/environment/server" do
|
41
|
-
config = stub(:Config, :projects => list(
|
42
|
-
stub(:name => :foo, :environments => list(
|
43
|
-
stub(:name => :bar, :servers => list(
|
44
|
-
server
|
45
|
-
))
|
46
|
-
))
|
47
|
-
))
|
48
|
-
|
49
|
-
parser(config, []).parse.should == server
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context "when there are multiple servers" do
|
54
|
-
let(:server1) { stub(:Server, :name => :s1) }
|
55
|
-
let(:server2) { stub(:Server, :name => :s2) }
|
56
|
-
|
57
|
-
it "should ask for server if it's not specified" do
|
58
|
-
config = stub(:Config, :projects => list(
|
59
|
-
stub(:name => :foo, :environments => list(
|
60
|
-
stub(:name => :bar, :servers => list(
|
61
|
-
server1, server2
|
62
|
-
))
|
63
|
-
))
|
64
|
-
))
|
65
|
-
|
66
|
-
expect do
|
67
|
-
parser(config, []).parse
|
68
|
-
end.to raise_error ArgumentError, /server/i
|
69
|
-
|
70
|
-
parser(config, ["s1"]).parse.should == server1
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context "when there are multiple environments" do
|
76
|
-
context "when environment not specified" do
|
77
|
-
it "should ask for environment"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def parser(*args)
|
84
|
-
TaketoArgvParser.new(*args)
|
85
|
-
end
|
86
|
-
|
87
|
-
def list(*items)
|
88
|
-
Taketo::Support::NamedNodesCollection.new(items)
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|