foreplay 0.9.13 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,92 +1,99 @@
1
1
  require 'net/ssh'
2
2
  require 'net/ssh/shell'
3
3
 
4
- class Foreplay::Engine::Remote
5
- include Foreplay
6
- attr_reader :server, :steps, :instructions
7
-
8
- def initialize(s, st, i)
9
- @server = s
10
- @steps = st
11
- @instructions = i
12
- end
13
-
14
- def deploy
15
- output = ''
16
-
17
- log "Connecting to #{host} on port #{port}", host: host
18
-
19
- # SSH connection
20
- session = start_session(host, user, options)
21
-
22
- log "Successfully connected to #{host} on port #{port}", host: host
23
-
24
- session.shell do |sh|
25
- steps.each { |step| output += Foreplay::Engine::Remote::Step.new(host, sh, step, instructions).execute }
4
+ require 'foreplay/engine/remote/check'
5
+ require 'foreplay/engine/remote/step'
6
+
7
+ module Foreplay
8
+ class Engine
9
+ class Remote
10
+ include Foreplay
11
+ attr_reader :server, :steps, :instructions
12
+
13
+ def initialize(s, st, i)
14
+ @server = s
15
+ @steps = st
16
+ @instructions = i
17
+ end
18
+
19
+ def deploy
20
+ output = ''
21
+
22
+ log "Connecting to #{host} on port #{port}", host: host
23
+
24
+ # SSH connection
25
+ session = start_session(host, user, options)
26
+
27
+ log "Successfully connected to #{host} on port #{port}", host: host
28
+
29
+ session.shell do |sh|
30
+ steps.each { |step| output += Foreplay::Engine::Remote::Step.new(host, sh, step, instructions).execute }
31
+ end
32
+
33
+ session.close
34
+ output
35
+ end
36
+
37
+ # Deployment check: just say what we would have done
38
+ def check
39
+ Foreplay::Engine::Remote::Check.new(host, steps, instructions).perform
40
+ end
41
+
42
+ def user
43
+ @user = instructions['user']
44
+ end
45
+
46
+ def host
47
+ @host ||= host_port[0]
48
+ end
49
+
50
+ def port
51
+ @port ||= (host_port[1] || 22)
52
+ end
53
+
54
+ def host_port
55
+ @host_port ||= server.split(':') # Parse host + port
56
+ end
57
+
58
+ def options
59
+ return @options if @options
60
+
61
+ @options = { verbose: :warn, port: port }
62
+ password = instructions['password']
63
+
64
+ if password.blank?
65
+ @options[:key_data] = [private_key]
66
+ else
67
+ @options[:password] = password
68
+ end
69
+
70
+ @options
71
+ end
72
+
73
+ def private_key
74
+ pk = instructions['private_key']
75
+ pk.blank? ? private_key_from_file : pk
76
+ end
77
+
78
+ def private_key_from_file
79
+ keyfile = instructions['keyfile']
80
+ keyfile.sub! '~', ENV['HOME'] || '/' unless keyfile.blank? # Remote shell won't expand this for us
81
+
82
+ terminate(
83
+ 'No authentication methods supplied. '\
84
+ 'You must supply a private key, key file or password in the configuration file'
85
+ ) if keyfile.blank?
86
+
87
+ # Get the key from the key file
88
+ log "Using private key from #{keyfile}"
89
+ File.read keyfile
90
+ end
91
+
92
+ def start_session(host, user, options)
93
+ Net::SSH.start(host, user, options)
94
+ rescue SocketError => e
95
+ terminate "There was a problem starting an ssh session on #{host}:\n#{e.message}"
96
+ end
26
97
  end
27
-
28
- session.close
29
- output
30
- end
31
-
32
- # Deployment check: just say what we would have done
33
- def check
34
- Foreplay::Engine::Remote::Check.new(host, steps, instructions).perform
35
- end
36
-
37
- def user
38
- @user = instructions['user']
39
- end
40
-
41
- def host
42
- @host ||= host_port[0]
43
- end
44
-
45
- def port
46
- @port ||= (host_port[1] || 22)
47
- end
48
-
49
- def host_port
50
- @host_port ||= server.split(':') # Parse host + port
51
- end
52
-
53
- def options
54
- return @options if @options
55
-
56
- @options = { verbose: :warn, port: port }
57
- password = instructions['password']
58
-
59
- if password.blank?
60
- @options[:key_data] = [private_key]
61
- else
62
- @options[:password] = password
63
- end
64
-
65
- @options
66
- end
67
-
68
- def private_key
69
- pk = instructions['private_key']
70
- pk.blank? ? private_key_from_file : pk
71
- end
72
-
73
- def private_key_from_file
74
- keyfile = instructions['keyfile']
75
- keyfile.sub! '~', ENV['HOME'] || '/' unless keyfile.blank? # Remote shell won't expand this for us
76
-
77
- terminate(
78
- 'No authentication methods supplied. '\
79
- 'You must supply a private key, key file or password in the configuration file'
80
- ) if keyfile.blank?
81
-
82
- # Get the key from the key file
83
- log "Using private key from #{keyfile}"
84
- File.read keyfile
85
- end
86
-
87
- def start_session(host, user, options)
88
- Net::SSH.start(host, user, options)
89
- rescue SocketError => e
90
- terminate "There was a problem starting an ssh session on #{host}:\n#{e.message}"
91
98
  end
92
99
  end
@@ -1,22 +1,26 @@
1
- class Foreplay::Engine::Role
2
- attr_reader :environment, :mode, :instructions, :servers
3
- def initialize(e, m, i)
4
- @environment = e
5
- @mode = m
6
- @instructions = i
7
- @servers = @instructions['servers']
1
+ module Foreplay
2
+ class Engine
3
+ class Role
4
+ attr_reader :environment, :mode, :instructions, :servers
5
+ def initialize(e, m, i)
6
+ @environment = e
7
+ @mode = m
8
+ @instructions = i
9
+ @servers = @instructions['servers']
8
10
 
9
- preposition = mode == :deploy ? 'to' : 'for'
11
+ preposition = mode == :deploy ? 'to' : 'for'
10
12
 
11
- return if @servers.length == 1
13
+ return if @servers.length == 1
12
14
 
13
- puts "#{mode.capitalize}ing #{instructions['name'].yellow} #{preposition} #{@servers.join(', ').yellow} "\
14
- "for the #{instructions['role'].dup.yellow} role in the #{environment.dup.yellow} environment..."
15
- end
15
+ puts "#{mode.capitalize}ing #{instructions['name'].yellow} #{preposition} #{@servers.join(', ').yellow} "\
16
+ "for the #{instructions['role'].dup.yellow} role in the #{environment.dup.yellow} environment..."
17
+ end
16
18
 
17
- def threads
18
- servers.map do |server|
19
- Thread.new { Foreplay::Engine::Server.new(environment, mode, instructions, server).execute }
19
+ def threads
20
+ servers.map do |server|
21
+ Thread.new { Foreplay::Engine::Server.new(environment, mode, instructions, server).execute }
22
+ end
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -1,34 +1,38 @@
1
- class Foreplay::Engine::Secrets
2
- attr_reader :environment, :secret_locations
1
+ module Foreplay
2
+ class Engine
3
+ class Secrets
4
+ attr_reader :environment, :secret_locations
3
5
 
4
- def initialize(e, sl)
5
- @environment = e
6
- @secret_locations = sl
7
- end
6
+ def initialize(e, sl)
7
+ @environment = e
8
+ @secret_locations = sl
9
+ end
8
10
 
9
- def fetch
10
- return unless secret_locations
11
+ def fetch
12
+ return unless secret_locations
11
13
 
12
- secrets = {}
14
+ secrets = {}
13
15
 
14
- secret_locations.each do |secret_location|
15
- secrets.merge! fetch_from(secret_location) || {}
16
- end
16
+ secret_locations.each do |secret_location|
17
+ secrets.merge! fetch_from(secret_location) || {}
18
+ end
17
19
 
18
- secrets
19
- end
20
+ secrets
21
+ end
20
22
 
21
- def fetch_from(secret_location)
22
- url = secret_location['url'] || return
23
+ def fetch_from(secret_location)
24
+ url = secret_location['url'] || return
23
25
 
24
- headers = secret_location['headers']
25
- header_string = headers.map { |k, v| " -H \"#{k}: #{v}\"" }.join if headers.is_a? Hash
26
- command = "curl -k -L#{header_string} #{url}".fake_erb
27
- secrets_all = YAML.load(`#{command}`)
28
- secrets = secrets_all[environment]
26
+ headers = secret_location['headers']
27
+ header_string = headers.map { |k, v| " -H \"#{k}: #{v}\"" }.join if headers.is_a? Hash
28
+ command = "curl -k -L#{header_string} #{url}".fake_erb
29
+ secrets_all = YAML.load(`#{command}`)
30
+ secrets = secrets_all[environment]
29
31
 
30
- secrets if secrets.is_a? Hash
31
- rescue Psych::SyntaxError
32
- nil
32
+ secrets if secrets.is_a? Hash
33
+ rescue Psych::SyntaxError
34
+ nil
35
+ end
36
+ end
33
37
  end
34
38
  end
@@ -1,68 +1,79 @@
1
- class Foreplay::Engine::Server
2
- include Foreplay::Engine::Port
3
- attr_reader :environment, :mode, :instructions, :server
1
+ module Foreplay
2
+ class Engine
3
+ class Server
4
+ include Foreplay::Engine::Port
5
+ attr_reader :environment, :mode, :instructions, :server
4
6
 
5
- def initialize(e, m, i, s)
6
- @environment = e
7
- @mode = m
8
- @instructions = i
9
- @server = s
10
- end
7
+ def initialize(e, m, i, s)
8
+ @environment = e
9
+ @mode = m
10
+ @instructions = i
11
+ @server = s
12
+ end
11
13
 
12
- def execute
13
- execute_announce
14
- foreman
15
- env
16
- Foreplay::Engine::Remote.new(server, steps, instructions).__send__ mode
17
- end
14
+ def execute
15
+ execute_announce
16
+ foreman
17
+ env
18
18
 
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
19
+ Foreplay::Engine::Remote.new(server, steps, instructions).__send__ mode
20
+ end
24
21
 
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
22
+ def execute_announce
23
+ preposition = mode == :deploy ? 'to' : 'for'
24
+ puts "#{mode.capitalize}ing #{name.yellow} #{preposition} #{host.yellow} "\
25
+ "for the #{role.dup.yellow} role in the #{environment.dup.yellow} environment"
26
+ end
33
27
 
34
- def env
35
- instructions['env'].merge!(
36
- 'HOME' => '$HOME',
37
- 'SHELL' => '$SHELL',
38
- 'PATH' => '$PATH:`which bundle`'
39
- )
40
- end
28
+ def foreman
29
+ instructions['foreman'] = {} unless instructions.key? 'foreman'
41
30
 
42
- def role
43
- @role ||= instructions['role']
44
- end
31
+ instructions['foreman'].merge!(
32
+ 'app' => current_service,
33
+ 'port' => current_port,
34
+ 'user' => user,
35
+ 'log' => "$HOME/#{path}/#{current_port}/log"
36
+ )
37
+ end
45
38
 
46
- def user
47
- @user ||= instructions['user']
48
- end
39
+ def env
40
+ instructions['env'] = {} unless instructions.key? 'env'
49
41
 
50
- def path
51
- return @path if @path
42
+ instructions['env'].merge!(
43
+ 'HOME' => '$HOME',
44
+ 'SHELL' => '$SHELL',
45
+ 'PATH' => '$PATH:`which bundle`',
46
+ 'GEM_HOME' => '$HOME/.rvm/gems/`rvm tools identifier`',
47
+ 'RAILS_ENV' => environment
48
+ )
49
+ end
52
50
 
53
- @path = instructions['path']
54
- @path.gsub! '%u', user
55
- @path.gsub! '%a', name
56
- @path
57
- end
51
+ def role
52
+ @role ||= instructions['role']
53
+ end
54
+
55
+ def user
56
+ @user ||= instructions['user']
57
+ end
58
+
59
+ def path
60
+ return @path if @path
61
+
62
+ @path = instructions['path']
63
+ @path.gsub! '%u', user
64
+ @path.gsub! '%a', name
65
+ @path
66
+ end
58
67
 
59
- def steps
60
- @steps ||= YAML.load(
61
- ERB.new(
62
- File.read(
63
- "#{File.dirname(__FILE__)}/steps.yml"
68
+ def steps
69
+ @steps ||= YAML.load(
70
+ ERB.new(
71
+ File.read(
72
+ "#{File.dirname(__FILE__)}/steps.yml"
73
+ )
74
+ ).result(binding)
64
75
  )
65
- ).result(binding)
66
- )
76
+ end
77
+ end
67
78
  end
68
79
  end
@@ -1,117 +1,121 @@
1
- class Foreplay::Engine::Step
2
- include Foreplay
3
- attr_reader :host, :step, :instructions
4
-
5
- def initialize(h, s, i)
6
- @host = h
7
- @step = s
8
- @instructions = i
9
- end
10
-
11
- def commands
12
- return @commands if @commands
13
-
14
- # Each step can be (1) a command or (2) a series of values to add to a file
15
- if step.key?('key')
16
- if instructions.key?(step['key'])
17
- build_commands
18
- else
19
- @commands = []
1
+ module Foreplay
2
+ class Engine
3
+ class Step
4
+ include Foreplay
5
+ attr_reader :host, :step, :instructions
6
+
7
+ def initialize(h, s, i)
8
+ @host = h
9
+ @step = s
10
+ @instructions = i
20
11
  end
21
- else
22
- # ...or just execute the command specified
23
- @commands = [command]
24
- end
25
-
26
- @commands
27
- end
28
12
 
29
- def build_commands
30
- step['silent'] = true
31
-
32
- if header?
33
- @commands = ["echo \"#{header}\" > #{filename}"]
34
- redirect
35
- else
36
- @commands = []
37
- end
13
+ def commands
14
+ return @commands if @commands
15
+
16
+ # Each step can be (1) a command or (2) a series of values to add to a file
17
+ if step.key?('key')
18
+ if instructions.key?(step['key'])
19
+ build_commands
20
+ else
21
+ @commands = []
22
+ end
23
+ else
24
+ # ...or just execute the command specified
25
+ @commands = [command]
26
+ end
27
+
28
+ @commands
29
+ end
38
30
 
39
- if instructions[key].is_a? Hash
40
- build_commands_from_hash
41
- else
42
- build_commands_from_string
43
- end
44
- end
31
+ def build_commands
32
+ step['silent'] = true
33
+
34
+ if header?
35
+ @commands = ["echo \"#{header}\" > #{filename}"]
36
+ redirect
37
+ else
38
+ @commands = []
39
+ end
40
+
41
+ if instructions[key].is_a? Hash
42
+ build_commands_from_hash
43
+ else
44
+ build_commands_from_string
45
+ end
46
+ end
45
47
 
46
- def build_commands_from_hash
47
- instructions[key].each do |k, v|
48
- @commands << "echo \"#{before}#{k}#{delimiter}#{v}#{after}\" #{redirect} #{filename}"
49
- end
50
- end
48
+ def build_commands_from_hash
49
+ instructions[key].each do |k, v|
50
+ @commands << "echo \"#{before}#{k}#{delimiter}#{v}#{after}\" #{redirect} #{filename}"
51
+ end
52
+ end
51
53
 
52
- def build_commands_from_string
53
- @commands << "echo \"#{before}#{delimiter}#{instructions[key]}#{after}\" #{redirect} #{filename}"
54
- end
54
+ def build_commands_from_string
55
+ @commands << "echo \"#{before}#{delimiter}#{instructions[key]}#{after}\" #{redirect} #{filename}"
56
+ end
55
57
 
56
- def redirect
57
- if @redirect
58
- '>>'
59
- else
60
- @redirect = true
61
- '>'
62
- end
63
- end
58
+ def redirect
59
+ if @redirect
60
+ '>>'
61
+ else
62
+ @redirect = true
63
+ '>'
64
+ end
65
+ end
64
66
 
65
- def command
66
- @command ||= step['command']
67
- end
67
+ def command
68
+ @command ||= step['command']
69
+ end
68
70
 
69
- def filename
70
- @filename ||= "#{path}#{prefix}#{key}#{suffix}"
71
- end
71
+ def filename
72
+ @filename ||= "#{path}#{prefix}#{key}#{suffix}"
73
+ end
72
74
 
73
- def key
74
- @key ||= step['key']
75
- end
75
+ def key
76
+ @key ||= step['key']
77
+ end
76
78
 
77
- def prefix
78
- @prefix ||= step['prefix'] || ''
79
- end
79
+ def prefix
80
+ @prefix ||= step['prefix'] || ''
81
+ end
80
82
 
81
- def suffix
82
- @suffix ||= step['suffix'] || ''
83
- end
83
+ def suffix
84
+ @suffix ||= step['suffix'] || ''
85
+ end
84
86
 
85
- def path
86
- @path ||= step['path'] || ''
87
- end
87
+ def path
88
+ @path ||= step['path'] || ''
89
+ end
88
90
 
89
- def before
90
- @before ||= step['before'] || ''
91
- end
91
+ def before
92
+ @before ||= step['before'] || ''
93
+ end
92
94
 
93
- def delimiter
94
- @delimiter ||= step['delimiter'] || ''
95
- end
95
+ def delimiter
96
+ @delimiter ||= step['delimiter'] || ''
97
+ end
96
98
 
97
- def after
98
- @after ||= step['after'] || ''
99
- end
99
+ def after
100
+ @after ||= step['after'] || ''
101
+ end
100
102
 
101
- def header
102
- @header ||= step['header']
103
- end
103
+ def header
104
+ @header ||= step['header']
105
+ end
104
106
 
105
- def header?
106
- header.present?
107
- end
107
+ def header?
108
+ header.present?
109
+ end
108
110
 
109
- def silent
110
- @silent ||= step['silent']
111
- end
111
+ def silent
112
+ @silent ||= step['silent']
113
+ end
112
114
 
113
- def announce
114
- log "#{(step['commentary'] || command).yellow}", host: host, silent: silent
115
- log command.cyan, host: host, silent: silent if instructions['verbose'] && step['commentary'] && command
115
+ def announce
116
+ log "#{(step['commentary'] || command).yellow}", host: host, silent: silent
117
+ log command.cyan, host: host, silent: silent if instructions['verbose'] && step['commentary'] && command
118
+ end
119
+ end
116
120
  end
117
121
  end