foreplay 0.9.8 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -9
- data/lib/foreplay.rb +1 -0
- data/lib/foreplay/engine.rb +16 -43
- data/lib/foreplay/engine/port.rb +66 -0
- data/lib/foreplay/engine/remote.rb +1 -1
- data/lib/foreplay/engine/remote/step.rb +14 -23
- data/lib/foreplay/engine/server.rb +25 -79
- data/lib/foreplay/engine/step.rb +69 -23
- data/lib/foreplay/version.rb +1 -1
- data/lib/hash.rb +30 -0
- data/spec/lib/foreplay/deploy_spec.rb +1 -1
- data/spec/lib/hash_spec.rb +30 -0
- metadata +6 -4
- data/spec/lib/foreplay/engine_spec.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54fa14c8cd58bcbcfa3d6ae58721785d2cbedf60
|
4
|
+
data.tar.gz: 78bfd857d56736431725d9d3b9eddc307f327c85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df13a59675a8e854d44d4b09c85723af3d8ef482c1fd726a5f3c1dd7169d5d0e17b77b8b4a6088fe122c74a6942dc42989ae44a4cf6edfe2bb0ee4f5a6d59dab
|
7
|
+
data.tar.gz: d98356701a491e17c6beea0abeedf0530515f13f6952bb3278d289089990a87b984fbf64bcf3e91671f7cc2658acca1f3737eb1609f31078ab0239ec52c53266
|
data/.rubocop.yml
CHANGED
@@ -42,14 +42,7 @@ LineLength:
|
|
42
42
|
|
43
43
|
MethodLength:
|
44
44
|
Description: 'Avoid methods longer than 10 lines of code.'
|
45
|
-
Max: 27 # 85
|
46
|
-
|
47
|
-
CyclomaticComplexity:
|
48
|
-
Description: 'Avoid complex methods.'
|
49
|
-
Max: 9
|
50
|
-
|
51
|
-
PerceivedComplexity:
|
52
|
-
Max: 11 # 17
|
45
|
+
Max: 18 # 27 # 85
|
53
46
|
|
54
47
|
AbcSize:
|
55
|
-
Max:
|
48
|
+
Max: 23 # 62
|
data/lib/foreplay.rb
CHANGED
@@ -5,6 +5,7 @@ require 'foreplay/engine'
|
|
5
5
|
require 'foreplay/engine/remote'
|
6
6
|
require 'foreplay/engine/remote/check'
|
7
7
|
require 'foreplay/engine/remote/step'
|
8
|
+
require 'foreplay/engine/port'
|
8
9
|
require 'foreplay/engine/role'
|
9
10
|
require 'foreplay/engine/secrets'
|
10
11
|
require 'foreplay/engine/server'
|
data/lib/foreplay/engine.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'string'
|
3
|
-
require '
|
3
|
+
require 'hash'
|
4
4
|
|
5
5
|
class Foreplay::Engine
|
6
6
|
include Foreplay
|
@@ -29,49 +29,19 @@ class Foreplay::Engine
|
|
29
29
|
puts "#{mode.capitalize}ing #{environment.dup.yellow} environment, "\
|
30
30
|
"#{explanatory_text(filters, 'role')}, #{explanatory_text(filters, 'server')}"
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
roles.each do |role, additional_instructions|
|
35
|
-
next if role == DEFAULTS_KEY # 'defaults' is not a role
|
36
|
-
next if filters.key?('role') && filters['role'] != role
|
37
|
-
|
38
|
-
threads.concat Foreplay::Engine::Role.new(
|
32
|
+
actionable_roles.map do |role, instructions|
|
33
|
+
Foreplay::Engine::Role.new(
|
39
34
|
environment,
|
40
35
|
mode,
|
41
|
-
build_instructions(role,
|
36
|
+
build_instructions(role, instructions)
|
42
37
|
).threads
|
43
|
-
end
|
44
|
-
|
45
|
-
threads.each(&:join)
|
38
|
+
end.flatten.each(&:join)
|
46
39
|
|
47
40
|
puts mode == :deploy ? 'Finished deployment' : 'Deployment configuration check was successful'
|
48
41
|
end
|
49
42
|
|
50
|
-
|
51
|
-
|
52
|
-
# h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
|
53
|
-
# h2 = { x: { y: [7,8,9] }, z: 'xyz' }
|
54
|
-
# h1.supermerge(h2)
|
55
|
-
# #=> {:x=>{:y=>[4, 5, 6, 7, 8, 9]}, :z=>[7, 8, 9, "xyz"]}
|
56
|
-
def supermerge(hash, other_hash)
|
57
|
-
fail 'supermerge only works if you pass two hashes. '\
|
58
|
-
"You passed a #{hash.class} and a #{other_hash.class}." unless hash.is_a?(Hash) && other_hash.is_a?(Hash)
|
59
|
-
|
60
|
-
new_hash = hash.deep_dup
|
61
|
-
|
62
|
-
other_hash.each_pair do |k, v|
|
63
|
-
tv = new_hash[k]
|
64
|
-
|
65
|
-
if tv.is_a?(Hash) && v.is_a?(Hash)
|
66
|
-
new_hash[k] = supermerge(tv, v)
|
67
|
-
elsif tv.is_a?(Array) || v.is_a?(Array)
|
68
|
-
new_hash[k] = Array.wrap(tv) + Array.wrap(v)
|
69
|
-
else
|
70
|
-
new_hash[k] = v
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
new_hash
|
43
|
+
def actionable_roles
|
44
|
+
roles.select { |role, _i| role != DEFAULTS_KEY && role != filters['role'] }
|
75
45
|
end
|
76
46
|
|
77
47
|
private
|
@@ -81,7 +51,7 @@ class Foreplay::Engine
|
|
81
51
|
end
|
82
52
|
|
83
53
|
def build_instructions(role, additional_instructions)
|
84
|
-
instructions = supermerge(
|
54
|
+
instructions = defaults.supermerge(additional_instructions)
|
85
55
|
instructions['role'] = role
|
86
56
|
required_keys = %w(name environment role servers path repository)
|
87
57
|
|
@@ -115,16 +85,19 @@ class Foreplay::Engine
|
|
115
85
|
'port' => 50_000
|
116
86
|
}
|
117
87
|
|
118
|
-
|
119
|
-
secrets = Foreplay::Engine::Secrets.new(environment, roles_all['secrets']).fetch || {}
|
120
|
-
@defaults['env'] = @defaults['env'].merge secrets
|
88
|
+
@defaults['env'].merge! secrets
|
121
89
|
@defaults['application'] = secrets
|
122
90
|
|
123
|
-
@defaults = supermerge(
|
124
|
-
@defaults = supermerge(
|
91
|
+
@defaults = @defaults.supermerge(roles_all[DEFAULTS_KEY]) if roles_all.key? DEFAULTS_KEY
|
92
|
+
@defaults = @defaults.supermerge(roles[DEFAULTS_KEY]) if roles.key? DEFAULTS_KEY
|
125
93
|
@defaults
|
126
94
|
end
|
127
95
|
|
96
|
+
# Secret environment variables
|
97
|
+
def secrets
|
98
|
+
@secrets ||= Foreplay::Engine::Secrets.new(environment, roles_all['secrets']).fetch || {}
|
99
|
+
end
|
100
|
+
|
128
101
|
def roles
|
129
102
|
@roles ||= roles_all[environment]
|
130
103
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Foreplay::Engine::Port
|
2
|
+
include Foreplay
|
3
|
+
|
4
|
+
def host
|
5
|
+
return @host if @host
|
6
|
+
@host, _p = server.split(':') # Parse host + port
|
7
|
+
@host
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
@name ||= instructions['name']
|
12
|
+
end
|
13
|
+
|
14
|
+
def current_port
|
15
|
+
@current_port ||= port_details['current_port']
|
16
|
+
end
|
17
|
+
|
18
|
+
def current_service
|
19
|
+
@current_service ||= port_details['current_service']
|
20
|
+
end
|
21
|
+
|
22
|
+
def former_port
|
23
|
+
@former_port ||= port_details['former_port']
|
24
|
+
end
|
25
|
+
|
26
|
+
def former_service
|
27
|
+
@former_service ||= port_details['former_service']
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_port_file
|
31
|
+
@current_port_file ||= ".foreplay/#{name}/current_port"
|
32
|
+
end
|
33
|
+
|
34
|
+
def port_steps
|
35
|
+
@port_steps ||= [
|
36
|
+
{
|
37
|
+
'command' => "mkdir -p .foreplay/#{name} && touch #{current_port_file} && cat #{current_port_file}",
|
38
|
+
'silent' => true
|
39
|
+
}
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
def port_details
|
44
|
+
return @port_details if @port_details
|
45
|
+
|
46
|
+
current_port_string = Foreplay::Engine::Remote.new(server, port_steps, instructions).__send__(mode).strip!
|
47
|
+
|
48
|
+
if current_port_string.blank?
|
49
|
+
puts "#{host}#{INDENT}No instance is currently deployed"
|
50
|
+
else
|
51
|
+
puts "#{host}#{INDENT}Current instance is using port #{current_port_string}"
|
52
|
+
end
|
53
|
+
|
54
|
+
cp = current_port_string.to_i
|
55
|
+
port = instructions['port']
|
56
|
+
ports = [port + 1000, port]
|
57
|
+
cp, fp = cp == port ? ports : ports.reverse
|
58
|
+
|
59
|
+
@port_details = {
|
60
|
+
'current_port' => cp,
|
61
|
+
'current_service' => "#{name}-#{cp}",
|
62
|
+
'former_port' => fp,
|
63
|
+
'former_service' => "#{name}-#{fp}"
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
@@ -22,7 +22,7 @@ class Foreplay::Engine::Remote
|
|
22
22
|
puts "#{host}#{INDENT}Successfully connected to #{host} on port #{port}"
|
23
23
|
|
24
24
|
session.shell do |sh|
|
25
|
-
steps.each { |step| output += Foreplay::Engine::Remote::Step.new(host, sh, step, instructions).
|
25
|
+
steps.each { |step| output += Foreplay::Engine::Remote::Step.new(host, sh, step, instructions).execute }
|
26
26
|
end
|
27
27
|
|
28
28
|
session.close
|
@@ -9,31 +9,22 @@ class Foreplay::Engine::Remote::Step
|
|
9
9
|
@instructions = i
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def execute
|
13
13
|
puts "#{host}#{INDENT}#{(step['commentary'] || step['command']).yellow}" unless step['silent'] == true
|
14
|
+
output Foreplay::Engine::Step.new(step, instructions).build.map { |command| execute_command(command) }.join
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
process.on_output do |_, o|
|
24
|
-
previous = o
|
25
|
-
output += previous
|
26
|
-
end
|
27
|
-
|
28
|
-
shell.wait!
|
29
|
-
|
30
|
-
if step['ignore_error'] == true || process.exit_status == 0
|
31
|
-
print output.gsub!(/^/, "#{host}#{INDENT * 2}") unless step['silent'] == true || output.blank?
|
32
|
-
else
|
33
|
-
terminate(output)
|
34
|
-
end
|
35
|
-
end
|
17
|
+
def execute_command(command)
|
18
|
+
o = ''
|
19
|
+
process = shell.execute command
|
20
|
+
process.on_output { |_, po| o = po }
|
21
|
+
shell.wait!
|
22
|
+
terminate(o) unless step['ignore_error'] == true || process.exit_status == 0
|
23
|
+
o
|
24
|
+
end
|
36
25
|
|
37
|
-
|
26
|
+
def output(o)
|
27
|
+
puts o.gsub!(/^/, "#{host}#{INDENT * 2}") unless step['silent'] == true || o.blank?
|
28
|
+
o
|
38
29
|
end
|
39
30
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Foreplay::Engine::Server
|
2
|
-
include Foreplay
|
2
|
+
include Foreplay::Engine::Port
|
3
3
|
attr_reader :environment, :mode, :instructions, :server
|
4
4
|
|
5
5
|
def initialize(e, m, i, s)
|
@@ -10,24 +10,33 @@ class Foreplay::Engine::Server
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def execute
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
execute_announce
|
14
|
+
foreman
|
15
|
+
env
|
16
|
+
Foreplay::Engine::Remote.new(server, steps, instructions).__send__ mode
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
def execute_announce
|
20
|
+
preposition = mode == :deploy ? 'to' : 'for'
|
21
|
+
puts "#{mode.capitalize}ing #{name.yellow} #{preposition} #{host.yellow} "\
|
22
|
+
"for the #{role.dup.yellow} role in the #{environment.dup.yellow} environment"
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
instructions['
|
27
|
-
|
28
|
-
|
25
|
+
def foreman
|
26
|
+
instructions['foreman'].merge!(
|
27
|
+
'app' => current_service,
|
28
|
+
'port' => current_port,
|
29
|
+
'user' => user,
|
30
|
+
'log' => "$HOME/#{path}/#{current_port}/log"
|
31
|
+
)
|
32
|
+
end
|
29
33
|
|
30
|
-
|
34
|
+
def env
|
35
|
+
instructions['env'].merge!(
|
36
|
+
'HOME' => '$HOME',
|
37
|
+
'SHELL' => '$SHELL',
|
38
|
+
'PATH' => '$PATH:`which bundle`'
|
39
|
+
)
|
31
40
|
end
|
32
41
|
|
33
42
|
def role
|
@@ -38,10 +47,6 @@ class Foreplay::Engine::Server
|
|
38
47
|
@user ||= instructions['user']
|
39
48
|
end
|
40
49
|
|
41
|
-
def name
|
42
|
-
@name ||= instructions['name']
|
43
|
-
end
|
44
|
-
|
45
50
|
def path
|
46
51
|
return @path if @path
|
47
52
|
|
@@ -51,12 +56,6 @@ class Foreplay::Engine::Server
|
|
51
56
|
@path
|
52
57
|
end
|
53
58
|
|
54
|
-
def host
|
55
|
-
return @host if @host
|
56
|
-
@host, _p = server.split(':') # Parse host + port
|
57
|
-
@host
|
58
|
-
end
|
59
|
-
|
60
59
|
def steps
|
61
60
|
@steps ||= YAML.load(
|
62
61
|
ERB.new(
|
@@ -66,57 +65,4 @@ class Foreplay::Engine::Server
|
|
66
65
|
).result(binding)
|
67
66
|
)
|
68
67
|
end
|
69
|
-
|
70
|
-
def current_port
|
71
|
-
@current_port ||= port_details['current_port']
|
72
|
-
end
|
73
|
-
|
74
|
-
def current_service
|
75
|
-
@current_service ||= port_details['current_service']
|
76
|
-
end
|
77
|
-
|
78
|
-
def former_port
|
79
|
-
@former_port ||= port_details['former_port']
|
80
|
-
end
|
81
|
-
|
82
|
-
def former_service
|
83
|
-
@former_service ||= port_details['former_service']
|
84
|
-
end
|
85
|
-
|
86
|
-
def current_port_file
|
87
|
-
@current_port_file ||= ".foreplay/#{name}/current_port"
|
88
|
-
end
|
89
|
-
|
90
|
-
def port_steps
|
91
|
-
@port_steps ||= [
|
92
|
-
{
|
93
|
-
'command' => "mkdir -p .foreplay/#{name} && touch #{current_port_file} && cat #{current_port_file}",
|
94
|
-
'silent' => true
|
95
|
-
}
|
96
|
-
]
|
97
|
-
end
|
98
|
-
|
99
|
-
def port_details
|
100
|
-
return @port_details if @port_details
|
101
|
-
|
102
|
-
current_port_string = Foreplay::Engine::Remote.new(server, port_steps, instructions).__send__(mode).strip!
|
103
|
-
|
104
|
-
if current_port_string.blank?
|
105
|
-
puts "#{host}#{INDENT}No instance is currently deployed"
|
106
|
-
else
|
107
|
-
puts "#{host}#{INDENT}Current instance is using port #{current_port_string}"
|
108
|
-
end
|
109
|
-
|
110
|
-
cp = current_port_string.to_i
|
111
|
-
port = instructions['port']
|
112
|
-
ports = [port + 1000, port]
|
113
|
-
cp, fp = cp == port ? ports : ports.reverse
|
114
|
-
|
115
|
-
@port_details = {
|
116
|
-
'current_port' => cp,
|
117
|
-
'current_service' => "#{name}-#{cp}",
|
118
|
-
'former_port' => fp,
|
119
|
-
'former_service' => "#{name}-#{fp}"
|
120
|
-
}
|
121
|
-
end
|
122
68
|
end
|
data/lib/foreplay/engine/step.rb
CHANGED
@@ -9,44 +9,90 @@ class Foreplay::Engine::Step
|
|
9
9
|
def build
|
10
10
|
# Each step can be (1) a command or (2) a series of values to add to a file
|
11
11
|
if step.key?('key')
|
12
|
-
instructions.key?(step['key']) ?
|
12
|
+
instructions.key?(step['key']) ? commands : []
|
13
13
|
else
|
14
14
|
# ...or just execute the command specified
|
15
15
|
[step['command']]
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
key = step['key']
|
22
|
-
prefix = step['prefix'] || ''
|
23
|
-
suffix = step['suffix'] || ''
|
24
|
-
path = step['path'] || ''
|
25
|
-
before = step['before'] || ''
|
26
|
-
delimiter = step['delimiter'] || ''
|
27
|
-
after = step['after'] || ''
|
19
|
+
def commands
|
20
|
+
return @commands if @commands
|
28
21
|
|
29
22
|
step['silent'] = true
|
30
|
-
filename = "#{path}#{prefix}#{key}#{suffix}"
|
31
23
|
|
32
|
-
if
|
33
|
-
commands = ["echo \"#{
|
34
|
-
redirect
|
24
|
+
if header?
|
25
|
+
@commands = ["echo \"#{header}\" > #{filename}"]
|
26
|
+
redirect
|
35
27
|
else
|
36
|
-
commands = []
|
37
|
-
redirect = '>'
|
28
|
+
@commands = []
|
38
29
|
end
|
39
30
|
|
40
31
|
if instructions[key].is_a? Hash
|
41
|
-
|
42
|
-
commands << "echo \"#{before}#{k}#{delimiter}#{v}#{after}\" #{redirect} #{filename}"
|
43
|
-
redirect = '>>'
|
44
|
-
end
|
32
|
+
build_commands_from_hash
|
45
33
|
else
|
46
|
-
|
47
|
-
redirect = '>>'
|
34
|
+
build_commands_from_string
|
48
35
|
end
|
49
36
|
|
50
|
-
commands
|
37
|
+
@commands
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_commands_from_hash
|
41
|
+
instructions[key].each do |k, v|
|
42
|
+
@commands << "echo \"#{before}#{k}#{delimiter}#{v}#{after}\" #{redirect} #{filename}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_commands_from_string
|
47
|
+
@commands << "echo \"#{before}#{delimiter}#{instructions[key]}#{after}\" #{redirect} #{filename}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def redirect
|
51
|
+
if @redirect
|
52
|
+
'>>'
|
53
|
+
else
|
54
|
+
@redirect = true
|
55
|
+
'>'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def filename
|
60
|
+
@filename ||= "#{path}#{prefix}#{key}#{suffix}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def key
|
64
|
+
@key ||= step['key']
|
65
|
+
end
|
66
|
+
|
67
|
+
def prefix
|
68
|
+
@prefix ||= step['prefix'] || ''
|
69
|
+
end
|
70
|
+
|
71
|
+
def suffix
|
72
|
+
@suffix ||= step['suffix'] || ''
|
73
|
+
end
|
74
|
+
|
75
|
+
def path
|
76
|
+
@path ||= step['path'] || ''
|
77
|
+
end
|
78
|
+
|
79
|
+
def before
|
80
|
+
@before ||= step['before'] || ''
|
81
|
+
end
|
82
|
+
|
83
|
+
def delimiter
|
84
|
+
@delimiter ||= step['delimiter'] || ''
|
85
|
+
end
|
86
|
+
|
87
|
+
def after
|
88
|
+
@after ||= step['after'] || ''
|
89
|
+
end
|
90
|
+
|
91
|
+
def header
|
92
|
+
@header ||= step['header']
|
93
|
+
end
|
94
|
+
|
95
|
+
def header?
|
96
|
+
header.present?
|
51
97
|
end
|
52
98
|
end
|
data/lib/foreplay/version.rb
CHANGED
data/lib/hash.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'active_support/core_ext/object'
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# Returns a new hash with +hash+ and +other_hash+ merged recursively, including arrays.
|
5
|
+
#
|
6
|
+
# h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
|
7
|
+
# h2 = { x: { y: [7,8,9] }, z: 'xyz' }
|
8
|
+
# h1.supermerge(h2)
|
9
|
+
# #=> {:x=>{:y=>[4, 5, 6, 7, 8, 9]}, :z=>[7, 8, 9, "xyz"]}
|
10
|
+
def supermerge(other_hash)
|
11
|
+
fail 'supermerge only works if you pass a hash. '\
|
12
|
+
"You passed a #{self.class} and a #{other_hash.class}." unless other_hash.is_a?(Hash)
|
13
|
+
|
14
|
+
new_hash = deep_dup
|
15
|
+
|
16
|
+
other_hash.each_pair do |k, v|
|
17
|
+
tv = new_hash[k]
|
18
|
+
|
19
|
+
if tv.is_a?(Hash) && v.is_a?(Hash)
|
20
|
+
new_hash[k] = tv.supermerge(v)
|
21
|
+
elsif tv.is_a?(Array) || v.is_a?(Array)
|
22
|
+
new_hash[k] = Array.wrap(tv) + Array.wrap(v)
|
23
|
+
else
|
24
|
+
new_hash[k] = v
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
new_hash
|
29
|
+
end
|
30
|
+
end
|
@@ -24,7 +24,7 @@ describe Foreplay::Launcher do
|
|
24
24
|
allow(session).to receive(:shell).and_yield(shell)
|
25
25
|
allow(shell).to receive(:execute).and_return(process)
|
26
26
|
allow(shell).to receive(:wait!).and_return(false)
|
27
|
-
allow(process).to receive(:on_output).and_yield(process, "output message\n")
|
27
|
+
allow(process).to receive(:on_output).and_yield(process, "output message 1\noutput message 2\n")
|
28
28
|
allow(process).to receive(:exit_status).and_return(0)
|
29
29
|
end
|
30
30
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hash'
|
3
|
+
|
4
|
+
describe Hash do
|
5
|
+
context '#supermerge' do
|
6
|
+
it 'should complain unless two hashes are passed to it' do
|
7
|
+
expect { {}.supermerge('y') }.to raise_error(RuntimeError)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should merge two simple hashes' do
|
11
|
+
expect({ a: 'x' }.supermerge(b: 'y')).to eq(a: 'x', b: 'y')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should merge two hashes both with arrays at the same key' do
|
15
|
+
expect({ a: ['x'] }.supermerge(a: ['y'])).to eq(a: %w(x y))
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should merge an array and a value at the same key' do
|
19
|
+
expect({ a: 'x' }.supermerge(a: ['y'])).to eq(a: %w(x y))
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should replace a value at the same key' do
|
23
|
+
expect({ a: 'x' }.supermerge(a: 'y')).to eq(a: 'y')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should merge two subhashes at the same key' do
|
27
|
+
expect({ a: { b: 'x' } }.supermerge(a: { c: 'y' })).to eq(a: { b: 'x', c: 'y' })
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreplay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xenapto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: foreman
|
@@ -222,6 +222,7 @@ files:
|
|
222
222
|
- lib/foreplay.rb
|
223
223
|
- lib/foreplay/cli.rb
|
224
224
|
- lib/foreplay/engine.rb
|
225
|
+
- lib/foreplay/engine/port.rb
|
225
226
|
- lib/foreplay/engine/remote.rb
|
226
227
|
- lib/foreplay/engine/remote/check.rb
|
227
228
|
- lib/foreplay/engine/remote/step.rb
|
@@ -235,11 +236,12 @@ files:
|
|
235
236
|
- lib/foreplay/setup.rb
|
236
237
|
- lib/foreplay/setup/foreplay.yml
|
237
238
|
- lib/foreplay/version.rb
|
239
|
+
- lib/hash.rb
|
238
240
|
- lib/string.rb
|
239
241
|
- spec/lib/foreplay/deploy_spec.rb
|
240
|
-
- spec/lib/foreplay/engine_spec.rb
|
241
242
|
- spec/lib/foreplay/secrets_spec.rb
|
242
243
|
- spec/lib/foreplay/setup_spec.rb
|
244
|
+
- spec/lib/hash_spec.rb
|
243
245
|
- spec/spec_helper.rb
|
244
246
|
homepage: https://github.com/Xenapto/foreplay
|
245
247
|
licenses:
|
@@ -271,7 +273,7 @@ test_files:
|
|
271
273
|
- features/setup.feature
|
272
274
|
- features/support/env.rb
|
273
275
|
- spec/lib/foreplay/deploy_spec.rb
|
274
|
-
- spec/lib/foreplay/engine_spec.rb
|
275
276
|
- spec/lib/foreplay/secrets_spec.rb
|
276
277
|
- spec/lib/foreplay/setup_spec.rb
|
278
|
+
- spec/lib/hash_spec.rb
|
277
279
|
- spec/spec_helper.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'foreplay'
|
3
|
-
|
4
|
-
describe Foreplay::Engine do
|
5
|
-
context '#supermerge' do
|
6
|
-
let(:engine) { Foreplay::Engine.new('b', 'b') }
|
7
|
-
|
8
|
-
it 'should complain unless two hashes are passed to it' do
|
9
|
-
expect { engine.supermerge('x', 'y') }.to raise_error(RuntimeError)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should merge two simple hashes' do
|
13
|
-
expect(engine.supermerge({ a: 'x' }, b: 'y')).to eq(a: 'x', b: 'y')
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'should merge two hashes both with arrays at the same key' do
|
17
|
-
expect(engine.supermerge({ a: ['x'] }, a: ['y'])).to eq(a: %w(x y))
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'should merge an array and a value at the same key' do
|
21
|
-
expect(engine.supermerge({ a: 'x' }, a: ['y'])).to eq(a: %w(x y))
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'should replace a value at the same key' do
|
25
|
-
expect(engine.supermerge({ a: 'x' }, a: 'y')).to eq(a: 'y')
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should merge two subhashes at the same key' do
|
29
|
-
expect(engine.supermerge({ a: { b: 'x' } }, a: { c: 'y' })).to eq(a: { b: 'x', c: 'y' })
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|