taketo 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://secure.travis-ci.org/v-yarotsky/taketo.png)](http://travis-ci.org/v-yarotsky/taketo)
|
5
5
|
[![Code Climate](https://codeclimate.com/badge.png)](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
|
-
|