foreplay 0.9.13 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/lib/foreplay/cli.rb +47 -45
- data/lib/foreplay/engine/defaults.rb +60 -0
- data/lib/foreplay/engine/logger.rb +50 -46
- data/lib/foreplay/engine/port.rb +65 -60
- data/lib/foreplay/engine/remote/check.rb +44 -38
- data/lib/foreplay/engine/remote/step.rb +34 -28
- data/lib/foreplay/engine/remote.rb +93 -86
- data/lib/foreplay/engine/role.rb +19 -15
- data/lib/foreplay/engine/secrets.rb +28 -24
- data/lib/foreplay/engine/server.rb +66 -55
- data/lib/foreplay/engine/step.rb +100 -96
- data/lib/foreplay/engine.rb +57 -106
- data/lib/foreplay/launcher.rb +9 -7
- data/lib/foreplay/setup.rb +26 -24
- data/lib/foreplay/version.rb +1 -1
- data/lib/foreplay.rb +14 -11
- data/spec/lib/foreplay/deploy_spec.rb +6 -2
- metadata +3 -4
- data/foreplay.rake +0 -28
- data/lib/foreplay/foreplay.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35a3ae418413c4a78a0c33ef41eb5e7168287e32
|
4
|
+
data.tar.gz: 954d074b1b34dc7643b3cd4a3b8daa433fa74ad1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20fd2bc4dc6f9eae22d3c098425b581d7b53d19bb0a1085ef8263edcb54b8bbd6f61b98f91ae78034d393316231203c97a90308b9f98cfc4c95af63569b8ddd8
|
7
|
+
data.tar.gz: aa5ad1cdc055544d768d7ffd63e2dd7766f5eddc23103ea4ab90c8a131efdb8d9b662a4e74e02a770856900c477d337123a8d2f2289797b24959b6a06a10bced
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/lib/foreplay/cli.rb
CHANGED
@@ -2,50 +2,52 @@ require 'thor'
|
|
2
2
|
require 'foreplay'
|
3
3
|
require 'foreplay/setup'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
5
|
+
module Foreplay
|
6
|
+
class CLI < Thor
|
7
|
+
desc 'deploy ENVIRONMENT', 'Deploys to specified environment'
|
8
|
+
|
9
|
+
method_option :role, aliases: '-r'
|
10
|
+
method_option :server, aliases: '-s'
|
11
|
+
method_option :config_file, aliases: '-f'
|
12
|
+
method_option :verbose, aliases: '-v'
|
13
|
+
|
14
|
+
def deploy(environment)
|
15
|
+
Foreplay::Launcher.start [:deploy, environment, options]
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'check ENVIRONMENT', 'Checks if configuration is OK for specified environment'
|
19
|
+
|
20
|
+
method_option :role, aliases: '-r'
|
21
|
+
method_option :server, aliases: '-s'
|
22
|
+
method_option :config_file, aliases: '-f'
|
23
|
+
method_option :verbose, aliases: '-v'
|
24
|
+
|
25
|
+
def check(environment)
|
26
|
+
Foreplay::Launcher.start [:check, environment, options]
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'setup', 'Create the Foreplay config file'
|
30
|
+
|
31
|
+
method_option :name, aliases: '-n'
|
32
|
+
method_option :repository, aliases: '-r'
|
33
|
+
method_option :user, aliases: '-u'
|
34
|
+
method_option :password
|
35
|
+
method_option :keyfile
|
36
|
+
method_option :private_key, aliases: '-k'
|
37
|
+
method_option :path, aliases: '-f'
|
38
|
+
method_option :port, aliases: '-p', type: :numeric
|
39
|
+
method_option :servers, aliases: '-s', type: :array
|
40
|
+
method_option :db_adapter, aliases: '-a'
|
41
|
+
method_option :db_encoding, aliases: '-e'
|
42
|
+
method_option :db_name, aliases: '-d'
|
43
|
+
method_option :db_pool, type: :numeric
|
44
|
+
method_option :db_host, aliases: '-h'
|
45
|
+
method_option :db_user
|
46
|
+
method_option :db_password
|
47
|
+
method_option :resque_redis
|
48
|
+
|
49
|
+
def setup
|
50
|
+
Foreplay::Setup.start
|
51
|
+
end
|
50
52
|
end
|
51
53
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Foreplay
|
2
|
+
class Engine
|
3
|
+
module Defaults
|
4
|
+
include Foreplay
|
5
|
+
|
6
|
+
DEFAULT_CONFIG_FILE = "#{Dir.getwd}/config/foreplay.yml"
|
7
|
+
DEFAULTS_KEY = 'defaults'
|
8
|
+
|
9
|
+
def defaults
|
10
|
+
return @defaults if @defaults
|
11
|
+
|
12
|
+
# Establish defaults
|
13
|
+
# First the default defaults
|
14
|
+
@defaults = {
|
15
|
+
'name' => File.basename(Dir.getwd),
|
16
|
+
'environment' => environment,
|
17
|
+
'port' => DEFAULT_PORT
|
18
|
+
}
|
19
|
+
|
20
|
+
@defaults['env'] = secrets
|
21
|
+
@defaults['application'] = secrets
|
22
|
+
@defaults = @defaults.supermerge(roles_all[DEFAULTS_KEY]) if roles_all.key? DEFAULTS_KEY
|
23
|
+
@defaults = @defaults.supermerge(roles[DEFAULTS_KEY]) if roles.key? DEFAULTS_KEY
|
24
|
+
@defaults
|
25
|
+
end
|
26
|
+
|
27
|
+
# Secret environment variables
|
28
|
+
def secrets
|
29
|
+
@secrets ||= (Foreplay::Engine::Secrets.new(environment, roles_all['secrets']).fetch || {})
|
30
|
+
end
|
31
|
+
|
32
|
+
def roles
|
33
|
+
@roles ||= roles_all[environment]
|
34
|
+
end
|
35
|
+
|
36
|
+
def roles_all
|
37
|
+
return @roles_all if @roles_all
|
38
|
+
|
39
|
+
@roles_all = YAML.load(File.read(config_file))
|
40
|
+
|
41
|
+
# This environment
|
42
|
+
unless @roles_all.key? environment
|
43
|
+
terminate("No deployment configuration defined for #{environment} environment.\nCheck #{config_file}")
|
44
|
+
end
|
45
|
+
|
46
|
+
@roles_all
|
47
|
+
rescue Errno::ENOENT
|
48
|
+
terminate "Can't find configuration file #{config_file}.\n"\
|
49
|
+
'Please run foreplay setup or create the file manually.'
|
50
|
+
rescue Psych::SyntaxError
|
51
|
+
terminate "I don't understand the configuration file #{config_file}.\n"\
|
52
|
+
'Please run foreplay setup or edit the file manually.'
|
53
|
+
end
|
54
|
+
|
55
|
+
def config_file
|
56
|
+
@config_file ||= (filters['config_file'] || DEFAULT_CONFIG_FILE)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,48 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
1
|
+
module Foreplay
|
2
|
+
class Engine
|
3
|
+
class Logger
|
4
|
+
INDENT = 4
|
5
|
+
MARGIN = 24
|
6
|
+
|
7
|
+
attr_reader :message, :options
|
8
|
+
|
9
|
+
def initialize(m, o = {})
|
10
|
+
@message = m
|
11
|
+
@options = o
|
12
|
+
|
13
|
+
output
|
14
|
+
end
|
15
|
+
|
16
|
+
def output
|
17
|
+
puts formatted_message unless silent?
|
18
|
+
end
|
19
|
+
|
20
|
+
def formatted_message
|
21
|
+
@formatted_message ||= header + message
|
22
|
+
.gsub(/\A\s+/, '')
|
23
|
+
.gsub(/\s+\z/, '')
|
24
|
+
.gsub(/(\r\n|\r|\n)/, "\\1#{margin}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def header
|
28
|
+
@header ||= (margin_format % header_content[0, margin_width - 1]).white
|
29
|
+
end
|
30
|
+
|
31
|
+
def header_content
|
32
|
+
@header_content ||= (options[:host] || '')
|
33
|
+
end
|
34
|
+
|
35
|
+
def margin
|
36
|
+
@margin ||= margin_format % ''
|
37
|
+
end
|
38
|
+
|
39
|
+
def silent?
|
40
|
+
@silent ||= (options[:silent] == true) || message.blank?
|
41
|
+
end
|
42
|
+
|
43
|
+
def margin_width
|
44
|
+
@margin_width ||= MARGIN + INDENT * (options[:indent] || 0)
|
45
|
+
end
|
46
|
+
|
47
|
+
def margin_format
|
48
|
+
@margin_format ||= "%-#{margin_width}s"
|
49
|
+
end
|
50
|
+
end
|
47
51
|
end
|
48
52
|
end
|
data/lib/foreplay/engine/port.rb
CHANGED
@@ -1,77 +1,82 @@
|
|
1
|
-
module Foreplay
|
2
|
-
|
1
|
+
module Foreplay
|
2
|
+
class Engine
|
3
|
+
module Port
|
4
|
+
include Foreplay
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def host
|
7
|
+
return @host if @host
|
8
|
+
@host, _p = server.split(':') # Parse host + port
|
9
|
+
@host
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
def name
|
13
|
+
@name ||= instructions['name']
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
def current_port
|
17
|
+
@current_port ||= port_details['current_port']
|
18
|
+
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
def current_service
|
21
|
+
@current_service ||= port_details['current_service']
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
def former_port
|
25
|
+
@former_port ||= port_details['former_port']
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
def former_service
|
29
|
+
@former_service ||= port_details['former_service']
|
30
|
+
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
def current_port_file
|
33
|
+
@current_port_file ||= ".foreplay/#{name}/current_port"
|
34
|
+
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
def port_steps
|
37
|
+
@port_steps ||= [
|
38
|
+
{
|
39
|
+
'command' => "mkdir -p .foreplay/#{name} && touch #{current_port_file} && cat #{current_port_file}",
|
40
|
+
'silent' => true
|
41
|
+
}
|
42
|
+
]
|
43
|
+
end
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
+
def current_port_remote
|
46
|
+
return @current_port_remote if @current_port_remote
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
@current_port_remote = Foreplay::Engine::Remote
|
49
|
+
.new(server, port_steps, instructions)
|
50
|
+
.__send__(mode)
|
51
|
+
.strip
|
52
|
+
.to_i
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
if @current_port_remote == 0
|
55
|
+
message = 'No instance is currently deployed'
|
56
|
+
@current_port_remote = DEFAULT_PORT + PORT_GAP
|
57
|
+
else
|
58
|
+
message = "Current instance is using port #{@current_port_remote}"
|
59
|
+
end
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
+
log message, host: host
|
62
|
+
@current_port_remote
|
63
|
+
end
|
61
64
|
|
62
|
-
|
63
|
-
|
65
|
+
def port_details
|
66
|
+
return @port_details if @port_details
|
64
67
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
68
|
+
cp = current_port_remote
|
69
|
+
port = instructions['port'].to_i
|
70
|
+
ports = [port + PORT_GAP, port]
|
71
|
+
cp, fp = cp == port ? ports : ports.reverse
|
69
72
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
@port_details = {
|
74
|
+
'current_port' => cp,
|
75
|
+
'current_service' => "#{name}-#{cp}",
|
76
|
+
'former_port' => fp,
|
77
|
+
'former_service' => "#{name}-#{fp}"
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
76
81
|
end
|
77
82
|
end
|
@@ -1,42 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
1
|
+
module Foreplay
|
2
|
+
class Engine
|
3
|
+
class Remote
|
4
|
+
class Check
|
5
|
+
include Foreplay
|
6
|
+
attr_reader :host, :steps, :instructions
|
7
|
+
|
8
|
+
def initialize(h, s, i)
|
9
|
+
@host = h
|
10
|
+
@steps = s
|
11
|
+
@instructions = i
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform
|
15
|
+
steps.each do |step|
|
16
|
+
log "#{(step['commentary'] || step['command']).yellow}", host: host, silent: step['silent']
|
17
|
+
|
18
|
+
if step.key? 'key'
|
19
|
+
list_file_contents step['key']
|
20
|
+
else
|
21
|
+
list_commands step
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
''
|
26
|
+
end
|
27
|
+
|
28
|
+
def list_file_contents(id)
|
29
|
+
i = instructions[id]
|
30
|
+
|
31
|
+
if i.is_a? Hash
|
32
|
+
i.each { |k, v| log "#{k}: #{v}", host: host, indent: 1 }
|
33
|
+
else
|
34
|
+
log i, host: host, indent: 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def list_commands(step)
|
39
|
+
commands = Foreplay::Engine::Step.new(host, step, instructions).commands
|
40
|
+
|
41
|
+
commands.each do |command|
|
42
|
+
log command, host: host, silent: step['silent']
|
43
|
+
end
|
44
|
+
end
|
19
45
|
end
|
20
46
|
end
|
21
|
-
|
22
|
-
''
|
23
|
-
end
|
24
|
-
|
25
|
-
def list_file_contents(id)
|
26
|
-
i = instructions[id]
|
27
|
-
|
28
|
-
if i.is_a? Hash
|
29
|
-
i.each { |k, v| log "#{k}: #{v}", host: host, indent: 1 }
|
30
|
-
else
|
31
|
-
log i, host: host, indent: 1
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def list_commands(step)
|
36
|
-
commands = Foreplay::Engine::Step.new(host, step, instructions).commands
|
37
|
-
|
38
|
-
commands.each do |command|
|
39
|
-
log command, host: host, silent: step['silent']
|
40
|
-
end
|
41
47
|
end
|
42
48
|
end
|
@@ -1,35 +1,41 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Foreplay
|
2
|
+
class Engine
|
3
|
+
class Remote
|
4
|
+
class Step
|
5
|
+
include Foreplay
|
6
|
+
attr_reader :host, :shell, :step, :instructions
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def initialize(h, sh, st, i)
|
9
|
+
@host = h
|
10
|
+
@shell = sh
|
11
|
+
@step = st
|
12
|
+
@instructions = i
|
13
|
+
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def execute
|
16
|
+
s = Foreplay::Engine::Step.new(host, step, instructions)
|
17
|
+
s.announce
|
18
|
+
output s.commands.map { |command| execute_command(command) }.join
|
19
|
+
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
def execute_command(command)
|
22
|
+
o = ''
|
23
|
+
process = shell.execute command
|
24
|
+
process.on_output { |_, po| o += po }
|
25
|
+
shell.wait!
|
26
|
+
terminate(o) unless step['ignore_error'] == true || process.exit_status == 0
|
27
|
+
o
|
28
|
+
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
def silent
|
31
|
+
@silent ||= instructions['verbose'] ? false : step['silent']
|
32
|
+
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
def output(o)
|
35
|
+
log o, host: host, silent: silent, indent: 1
|
36
|
+
o
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|