foreplay 0.8.0 → 0.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a1dbd3b362d4784a5b5878bba559b812106e9c8
4
- data.tar.gz: fe058cb4c473892115225f78587d0f88929bc745
3
+ metadata.gz: 792102ce293a729754f551ac87b6289ff1c7c81c
4
+ data.tar.gz: 7d74c817f3aa6b8209b73a0d10cd7202a24a37dc
5
5
  SHA512:
6
- metadata.gz: 08f86cc7dfb91d26d9865dbfdcd05adf603e1f5afa690e51503215b2005ed3c93982fca7b798589b6de490184f0a3ddd875a6068ce14ed00b0ba1c871065b4cc
7
- data.tar.gz: 3d360c7d1ab0a3fdd61d25eaa46d6da0ba38f88df993daa78ac180f57979d43e9073390de2842abb566d63028cf3c6238ad151a69b1c7a37c5ebe8a6384d4974
6
+ metadata.gz: 63dea290c9868a255eaefa222a159d8f9bc38bd8e9df82e7834cf33fc50b77f770b894d14b8070398aa186053ae383b73c45238ee04432f408fd3a35cc394185
7
+ data.tar.gz: 40eddda360ffb3caeb8338e96209213f5276893113968ce9b8488434cda06fbd5905178473f70ca0cceafab0b2f2e1d7be6d53493dcb3e71df5de75f11707cc5
data/foreplay.gemspec CHANGED
@@ -17,9 +17,9 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features|coverage)\/})
18
18
  spec.require_paths = ['lib']
19
19
 
20
- spec.add_runtime_dependency 'activesupport', '>= 3.2'
21
- spec.add_runtime_dependency 'foreman', '>= 0.76'
22
- spec.add_runtime_dependency 'ssh-shell', '>= 0.4'
20
+ spec.add_runtime_dependency 'foreman', '>= 0.76', '< 1.0'
21
+ spec.add_runtime_dependency 'ssh-shell', '>= 0.4', '< 1.0'
22
+ spec.add_runtime_dependency 'activesupport', '>= 3.2', '< 5.0'
23
23
 
24
24
  spec.add_development_dependency 'bundler', '~> 1.9'
25
25
  spec.add_development_dependency 'rake', '~> 10.4'
data/lib/foreplay/cli.rb CHANGED
@@ -7,6 +7,7 @@ class Foreplay::CLI < Thor
7
7
 
8
8
  method_option :role, aliases: '-r'
9
9
  method_option :server, aliases: '-s'
10
+ method_option :config_file, aliases: '-f'
10
11
 
11
12
  def deploy(environment)
12
13
  Foreplay::Launcher.start [:deploy, environment, options]
@@ -16,6 +17,7 @@ class Foreplay::CLI < Thor
16
17
 
17
18
  method_option :role, aliases: '-r'
18
19
  method_option :server, aliases: '-s'
20
+ method_option :config_file, aliases: '-f'
19
21
 
20
22
  def check(environment)
21
23
  Foreplay::Launcher.start [:check, environment, options]
@@ -1,4 +1,5 @@
1
1
  require 'net/ssh'
2
+ require 'pp' # debug
2
3
 
3
4
  class Foreplay::Engine::Remote
4
5
  include Foreplay
@@ -56,15 +57,29 @@ class Foreplay::Engine::Remote
56
57
  def check
57
58
  steps.each do |step|
58
59
  puts "#{host}#{INDENT}#{(step['commentary'] || step['command']).yellow}" unless step['silent'] == true
59
- commands = Foreplay::Engine::Step.new(step, instructions).build
60
- commands.each { |command| puts "#{host}#{INDENT * 2}#{command}" unless step['silent'] }
60
+
61
+ if step.key? 'key'
62
+ i = instructions[step['key']]
63
+
64
+ if i.is_a? Hash
65
+ i.each { |k, v| puts "#{host}#{INDENT * 2}#{k}: #{v}" }
66
+ else
67
+ puts "#{host}#{INDENT * 2}#{i}"
68
+ end
69
+ else
70
+ commands = Foreplay::Engine::Step.new(step, instructions).build
71
+
72
+ commands.each do |command|
73
+ puts "#{host}#{INDENT * 2}#{command}" unless step['silent']
74
+ end
75
+ end
61
76
  end
62
77
 
63
78
  ''
64
79
  end
65
80
 
66
81
  def user
67
- @user = instructions[:user]
82
+ @user = instructions['user']
68
83
  end
69
84
 
70
85
  def host
@@ -82,9 +97,9 @@ class Foreplay::Engine::Remote
82
97
  def options
83
98
  return @options if @options
84
99
 
85
- password = instructions[:password]
86
- keyfile = instructions[:keyfile]
87
- private_key = instructions[:private_key]
100
+ password = instructions['password']
101
+ keyfile = instructions['keyfile']
102
+ private_key = instructions['private_key']
88
103
 
89
104
  keyfile.sub! '~', ENV['HOME'] || '/' unless keyfile.blank? # Remote shell won't expand this for us
90
105
 
@@ -1,18 +1,17 @@
1
1
  class Foreplay::Engine::Role
2
2
  attr_reader :environment, :mode, :instructions, :servers
3
-
4
3
  def initialize(e, m, i)
5
4
  @environment = e
6
5
  @mode = m
7
6
  @instructions = i
8
- @servers = @instructions[:servers]
7
+ @servers = @instructions['servers']
9
8
 
10
9
  preposition = mode == :deploy ? 'to' : 'for'
11
10
 
12
11
  return if @servers.length == 1
13
12
 
14
- puts "#{mode.capitalize}ing #{instructions[:name].yellow} #{preposition} #{@servers.join(', ').yellow} "\
15
- "for the #{instructions[:role].dup.yellow} role in the #{environment.dup.yellow} environment..."
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..."
16
15
  end
17
16
 
18
17
  def threads
@@ -0,0 +1,32 @@
1
+ class Foreplay::Engine::Secrets
2
+ attr_reader :environment, :secret_locations
3
+
4
+ def initialize(e, sl)
5
+ @environment = e
6
+ @secret_locations = sl
7
+ end
8
+
9
+ def fetch
10
+ return unless secret_locations
11
+
12
+ secrets = {}
13
+
14
+ secret_locations.each do |secret_location|
15
+ secrets.merge! fetch_from(secret_location)
16
+ end
17
+
18
+ secrets
19
+ end
20
+
21
+ def fetch_from(secret_location)
22
+ return unless secret_location['url']
23
+
24
+ headers = secret_location['headers'].map { |k, v| " -H \"#{k}: #{v}\"" }.join
25
+ command = "curl -k -L#{headers} #{secret_location['url']}"
26
+
27
+ secrets_all = YAML.load(`#{command}`)
28
+ secrets_all[environment]
29
+ rescue Psych::SyntaxError
30
+ nil
31
+ end
32
+ end
@@ -1,5 +1,3 @@
1
- require 'active_support/inflector'
2
-
3
1
  class Foreplay::Engine::Server
4
2
  include Foreplay
5
3
  attr_reader :environment, :mode, :instructions, :server
@@ -18,35 +16,36 @@ class Foreplay::Engine::Server
18
16
  message += "for the #{role.dup.yellow} role in the #{environment.dup.yellow} environment"
19
17
  puts message
20
18
 
21
- instructions[:foreman]['app'] = current_service
22
- instructions[:foreman]['port'] = current_port
23
- instructions[:foreman]['user'] = user
24
- instructions[:foreman]['log'] = "$HOME/#{path}/#{current_port}/log"
19
+ # Contents of .foreman file
20
+ instructions['foreman']['app'] = current_service
21
+ instructions['foreman']['port'] = current_port
22
+ instructions['foreman']['user'] = user
23
+ instructions['foreman']['log'] = "$HOME/#{path}/#{current_port}/log"
25
24
 
26
25
  # Contents of .env file
27
- instructions[:env]['HOME'] = '$HOME'
28
- instructions[:env]['SHELL'] = '$SHELL'
29
- instructions[:env]['PATH'] = '$PATH:`which bundle`'
26
+ instructions['env']['HOME'] = '$HOME'
27
+ instructions['env']['SHELL'] = '$SHELL'
28
+ instructions['env']['PATH'] = '$PATH:`which bundle`'
30
29
 
31
30
  Foreplay::Engine::Remote.new(server, steps, instructions).__send__ mode
32
31
  end
33
32
 
34
33
  def role
35
- @role ||= instructions[:role]
34
+ @role ||= instructions['role']
36
35
  end
37
36
 
38
37
  def user
39
- @user ||= instructions[:user]
38
+ @user ||= instructions['user']
40
39
  end
41
40
 
42
41
  def name
43
- @name ||= instructions[:name]
42
+ @name ||= instructions['name']
44
43
  end
45
44
 
46
45
  def path
47
46
  return @path if @path
48
47
 
49
- @path = instructions[:path]
48
+ @path = instructions['path']
50
49
  @path.gsub! '%u', user
51
50
  @path.gsub! '%a', name
52
51
  @path
@@ -69,19 +68,19 @@ class Foreplay::Engine::Server
69
68
  end
70
69
 
71
70
  def current_port
72
- @current_port ||= port_details[:current_port]
71
+ @current_port ||= port_details['current_port']
73
72
  end
74
73
 
75
74
  def current_service
76
- @current_service ||= port_details[:current_service]
75
+ @current_service ||= port_details['current_service']
77
76
  end
78
77
 
79
78
  def former_port
80
- @former_port ||= port_details[:former_port]
79
+ @former_port ||= port_details['former_port']
81
80
  end
82
81
 
83
82
  def former_service
84
- @former_service ||= port_details[:former_service]
83
+ @former_service ||= port_details['former_service']
85
84
  end
86
85
 
87
86
  def current_port_file
@@ -109,15 +108,15 @@ class Foreplay::Engine::Server
109
108
  end
110
109
 
111
110
  cp = current_port_string.to_i
112
- port = instructions[:port]
111
+ port = instructions['port']
113
112
  ports = [port + 1000, port]
114
113
  cp, fp = cp == port ? ports : ports.reverse
115
114
 
116
115
  @port_details = {
117
- current_port: cp,
118
- current_service: "#{name}-#{cp}",
119
- former_port: fp,
120
- former_service: "#{name}-#{fp}"
116
+ 'current_port' => cp,
117
+ 'current_service' => "#{name}-#{cp}",
118
+ 'former_port' => fp,
119
+ 'former_service' => "#{name}-#{fp}"
121
120
  }
122
121
  end
123
122
  end
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  - command: "echo Foreplay version <%= VERSION %>"
3
3
  commentary: "Foreplay running from <%= `hostname -f` %><%= `which foreman` %>"
4
- - command: "mkdir -p <%= path %> && cd <%= path %> && rm -rf <%= current_port %> && git clone -b <%= instructions[:branch] || 'master' %> <%= instructions[:repository] %> <%= current_port %>"
5
- commentary: "Cloning <%= instructions[:branch] || 'master' %> branch of repository <%= instructions[:repository] %>"
4
+ - command: "mkdir -p <%= path %> && cd <%= path %> && rm -rf <%= current_port %> && git clone -b <%= instructions['branch'] || 'master' %> <%= instructions['repository'] %> <%= current_port %>"
5
+ commentary: "Cloning <%= instructions['branch'] || 'master' %> branch of repository <%= instructions['repository'] %>"
6
6
  - command: "rvm rvmrc trust <%= current_port %>"
7
7
  commentary: 'Trusting the .rvmrc file for the new instance'
8
8
  - command: "rvm rvmrc warning ignore <%= current_port %>"
@@ -14,22 +14,29 @@
14
14
  commentary: 'If you have a .rvmrc file there may be a delay now while we install a new ruby'
15
15
  - command: 'if [ -f .ruby-version ] ; then rvm install `cat .ruby-version` ; else echo "No .ruby-version file found" ; fi'
16
16
  commentary: 'If you have a .ruby-version file there may be a delay now while we install a new ruby'
17
- - key: :env
17
+ - key: 'env'
18
18
  delimiter: '='
19
19
  prefix: '.'
20
20
  commentary: 'Building .env'
21
- - key: :foreman
21
+ - key: 'foreman'
22
22
  delimiter: ': '
23
23
  prefix: '.'
24
24
  commentary: 'Building .foreman'
25
- - key: :database
25
+ - key: 'database'
26
26
  delimiter: ': '
27
27
  suffix: '.yml'
28
28
  commentary: 'Building config/database.yml'
29
29
  before: ' '
30
30
  header: "<%= environment %>:"
31
31
  path: 'config/'
32
- - key: :resque
32
+ - key: 'application'
33
+ delimiter: ': '
34
+ suffix: '.yml'
35
+ commentary: 'Building config/application.yml'
36
+ before: ' '
37
+ header: "<%= environment %>:"
38
+ path: 'config/'
39
+ - key: 'resque'
33
40
  delimiter: ': '
34
41
  suffix: '.yml'
35
42
  commentary: 'Building config/resque.yml'
@@ -1,12 +1,13 @@
1
1
  require 'yaml'
2
2
  require 'string'
3
+ require 'active_support/core_ext/object'
3
4
 
4
5
  class Foreplay::Engine
5
6
  include Foreplay
6
- attr_reader :environment, :filters, :mode
7
+ attr_reader :mode, :environment, :filters
7
8
 
8
- DEFAULTS_KEY = 'defaults'
9
- CONFIG_FILE = "#{Dir.getwd}/config/foreplay.yml"
9
+ DEFAULT_CONFIG_FILE = "#{Dir.getwd}/config/foreplay.yml"
10
+ DEFAULTS_KEY = 'defaults'
10
11
 
11
12
  def initialize(e, f)
12
13
  @environment = e
@@ -56,7 +57,7 @@ class Foreplay::Engine
56
57
  fail 'supermerge only works if you pass two hashes. '\
57
58
  "You passed a #{hash.class} and a #{other_hash.class}." unless hash.is_a?(Hash) && other_hash.is_a?(Hash)
58
59
 
59
- new_hash = hash.deep_dup.with_indifferent_access
60
+ new_hash = hash.deep_dup
60
61
 
61
62
  other_hash.each_pair do |k, v|
62
63
  tv = new_hash[k]
@@ -76,21 +77,21 @@ class Foreplay::Engine
76
77
  private
77
78
 
78
79
  def explanatory_text(hsh, key)
79
- hsh.key?(key) ? "#{hsh[key].dup.yellow} #{key}" : "all #{key.pluralize}"
80
+ hsh.key?(key) ? "#{hsh[key].dup.yellow} #{key}" : "all #{key}s"
80
81
  end
81
82
 
82
83
  def build_instructions(role, additional_instructions)
83
- instructions = supermerge(defaults, additional_instructions).symbolize_keys
84
- instructions[:role] = role
85
- required_keys = [:name, :environment, :role, :servers, :path, :repository]
84
+ instructions = supermerge(defaults, additional_instructions)
85
+ instructions['role'] = role
86
+ required_keys = %w(name environment role servers path repository)
86
87
 
87
88
  required_keys.each do |key|
88
89
  next if instructions.key? key
89
- terminate("Required key #{key} not found in instructions for #{environment} environment.\nCheck #{CONFIG_FILE}")
90
+ terminate("Required key #{key} not found in instructions for #{environment} environment.\nCheck #{config_file}")
90
91
  end
91
92
 
92
93
  # Apply server filter
93
- instructions[:servers] &= server_filter if server_filter
94
+ instructions['servers'] &= server_filter if server_filter
94
95
  instructions
95
96
  end
96
97
 
@@ -98,20 +99,30 @@ class Foreplay::Engine
98
99
  @server_filter ||= filters['server'].split(',') if filters.key?('server')
99
100
  end
100
101
 
102
+ def config_file
103
+ @config_file ||= (filters['config_file'] || DEFAULT_CONFIG_FILE)
104
+ end
105
+
101
106
  def defaults
102
107
  return @defaults if @defaults
103
108
 
104
109
  # Establish defaults
105
110
  # First the default defaults
106
111
  @defaults = {
107
- name: File.basename(Dir.getwd),
108
- environment: environment,
109
- env: { 'RAILS_ENV' => environment },
110
- port: 50_000
112
+ 'name' => File.basename(Dir.getwd),
113
+ 'environment' => environment,
114
+ 'env' => { 'RAILS_ENV' => environment },
115
+ 'port' => 50_000
111
116
  }
112
117
 
118
+ # Add secret environment variables
119
+ secrets = Foreplay::Engine::Secrets.new(environment, roles_all['secrets']).fetch || {}
120
+ @defaults['env'] = @defaults['env'].merge secrets
121
+ @defaults['application'] = secrets
122
+
113
123
  @defaults = supermerge(@defaults, roles_all[DEFAULTS_KEY]) if roles_all.key? DEFAULTS_KEY
114
124
  @defaults = supermerge(@defaults, roles[DEFAULTS_KEY]) if roles.key? DEFAULTS_KEY
125
+ @defaults
115
126
  end
116
127
 
117
128
  def roles
@@ -121,18 +132,18 @@ class Foreplay::Engine
121
132
  def roles_all
122
133
  return @roles_all if @roles_all
123
134
 
124
- @roles_all = YAML.load(File.read(CONFIG_FILE))
135
+ @roles_all = YAML.load(File.read(config_file))
125
136
 
126
137
  # This environment
127
138
  unless @roles_all.key? environment
128
- terminate("No deployment configuration defined for #{environment} environment.\nCheck #{CONFIG_FILE}")
139
+ terminate("No deployment configuration defined for #{environment} environment.\nCheck #{config_file}")
129
140
  end
130
141
 
131
142
  @roles_all
132
143
  rescue Errno::ENOENT
133
- terminate "Can't find configuration file #{CONFIG_FILE}.\nPlease run foreplay setup or create the file manually."
144
+ terminate "Can't find configuration file #{config_file}.\nPlease run foreplay setup or create the file manually."
134
145
  rescue Psych::SyntaxError
135
- terminate "I don't understand the configuration file #{CONFIG_FILE}.\n"\
146
+ terminate "I don't understand the configuration file #{config_file}.\n"\
136
147
  'Please run foreplay setup or edit the file manually.'
137
148
  end
138
149
  end
@@ -1,6 +1,3 @@
1
- require 'active_support/core_ext/object'
2
- require 'active_support/core_ext/hash'
3
-
4
1
  module Foreplay
5
2
  INDENT = "\t"
6
3
 
@@ -1,3 +1,3 @@
1
1
  module Foreplay
2
- VERSION = '0.8.0'
2
+ VERSION = '0.9.0'
3
3
  end
data/lib/foreplay.rb CHANGED
@@ -4,5 +4,6 @@ require 'foreplay/launcher'
4
4
  require 'foreplay/engine'
5
5
  require 'foreplay/engine/remote'
6
6
  require 'foreplay/engine/role'
7
+ require 'foreplay/engine/secrets'
7
8
  require 'foreplay/engine/server'
8
9
  require 'foreplay/engine/step'
@@ -10,23 +10,23 @@ describe Foreplay::Engine do
10
10
  end
11
11
 
12
12
  it 'should merge two simple hashes' do
13
- expect(engine.supermerge({ a: 'x' }, b: 'y')).to eq('a' => 'x', 'b' => 'y')
13
+ expect(engine.supermerge({ a: 'x' }, b: 'y')).to eq(a: 'x', b: 'y')
14
14
  end
15
15
 
16
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))
17
+ expect(engine.supermerge({ a: ['x'] }, a: ['y'])).to eq(a: %w(x y))
18
18
  end
19
19
 
20
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))
21
+ expect(engine.supermerge({ a: 'x' }, a: ['y'])).to eq(a: %w(x y))
22
22
  end
23
23
 
24
24
  it 'should replace a value at the same key' do
25
- expect(engine.supermerge({ a: 'x' }, a: 'y')).to eq('a' => 'y')
25
+ expect(engine.supermerge({ a: 'x' }, a: 'y')).to eq(a: 'y')
26
26
  end
27
27
 
28
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' })
29
+ expect(engine.supermerge({ a: { b: 'x' } }, a: { c: 'y' })).to eq(a: { b: 'x', c: 'y' })
30
30
  end
31
31
  end
32
32
  end
metadata CHANGED
@@ -1,57 +1,75 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreplay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xenapto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-28 00:00:00.000000000 Z
11
+ date: 2015-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: foreman
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.2'
19
+ version: '0.76'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '1.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: '3.2'
29
+ version: '0.76'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
27
33
  - !ruby/object:Gem::Dependency
28
- name: foreman
34
+ name: ssh-shell
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: '0.76'
39
+ version: '0.4'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '1.0'
34
43
  type: :runtime
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
47
  - - ">="
39
48
  - !ruby/object:Gem::Version
40
- version: '0.76'
49
+ version: '0.4'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '1.0'
41
53
  - !ruby/object:Gem::Dependency
42
- name: ssh-shell
54
+ name: activesupport
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
57
  - - ">="
46
58
  - !ruby/object:Gem::Version
47
- version: '0.4'
59
+ version: '3.2'
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '5.0'
48
63
  type: :runtime
49
64
  prerelease: false
50
65
  version_requirements: !ruby/object:Gem::Requirement
51
66
  requirements:
52
67
  - - ">="
53
68
  - !ruby/object:Gem::Version
54
- version: '0.4'
69
+ version: '3.2'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '5.0'
55
73
  - !ruby/object:Gem::Dependency
56
74
  name: bundler
57
75
  requirement: !ruby/object:Gem::Requirement
@@ -206,6 +224,7 @@ files:
206
224
  - lib/foreplay/engine.rb
207
225
  - lib/foreplay/engine/remote.rb
208
226
  - lib/foreplay/engine/role.rb
227
+ - lib/foreplay/engine/secrets.rb
209
228
  - lib/foreplay/engine/server.rb
210
229
  - lib/foreplay/engine/step.rb
211
230
  - lib/foreplay/engine/steps.yml