foreplay 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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