foreplay 0.9.13 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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