docker_rails_proxy 0.0.0 → 0.0.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.
- checksums.yaml +4 -4
- data/lib/docker_rails_proxy/cli.rb +37 -0
- data/lib/docker_rails_proxy/commands/build.rb +77 -0
- data/lib/docker_rails_proxy/commands/bundle.rb +8 -0
- data/lib/docker_rails_proxy/commands/compose/down.rb +15 -0
- data/lib/docker_rails_proxy/commands/compose/override.rb +20 -0
- data/lib/docker_rails_proxy/commands/compose/proxy.rb +10 -0
- data/lib/docker_rails_proxy/commands/compose/up.rb +131 -0
- data/lib/docker_rails_proxy/commands/compose.rb +18 -0
- data/lib/docker_rails_proxy/commands/data_bags.rb +91 -0
- data/lib/docker_rails_proxy/commands/rails.rb +39 -0
- data/lib/docker_rails_proxy/commands/rake.rb +8 -0
- data/lib/docker_rails_proxy/commands/rspec.rb +8 -0
- data/lib/docker_rails_proxy/commands/spring.rb +8 -0
- data/lib/docker_rails_proxy/commands/ssh.rb +29 -0
- data/lib/docker_rails_proxy/concerns/callbacks.rb +115 -0
- data/lib/docker_rails_proxy/concerns/inheritable_attributes.rb +46 -0
- data/lib/docker_rails_proxy/concerns/rsync.rb +91 -0
- data/lib/docker_rails_proxy/extends/colorization.rb +36 -0
- data/lib/docker_rails_proxy/extends/string_support.rb +21 -0
- data/lib/docker_rails_proxy/version.rb +3 -0
- data/lib/docker_rails_proxy.rb +103 -0
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c565af80fd33cee75c95b7ada9c8c7bdb42f0bf0
|
4
|
+
data.tar.gz: 288e91970419af210886a50ab0d78cbd95a3f203
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bb58cfef7d4fbf1e344b61c32117323e5730dd879938bf1d10033abb408e8a3e029a833235474d55a0166b61ac1750ff073102246568080ee9437e17b24c45c
|
7
|
+
data.tar.gz: 216df1896cb8ac1fbdef8994c87f50a863e710ef49ef660144ac30eb0f980d2822279332c8855593706b3fdf134abe56e1da681cc542303e7a068bc559c3194d
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
class Cli
|
3
|
+
class << self
|
4
|
+
def invoke(arguments)
|
5
|
+
command, *args = arguments
|
6
|
+
|
7
|
+
if command.nil?
|
8
|
+
$stderr.puts <<-EOF
|
9
|
+
#{"bin/#{APP_NAME} requires 1 argument.".bold}
|
10
|
+
|
11
|
+
#{"Usage: bin/#{APP_NAME} <command> [<args>]".bold}
|
12
|
+
EOF
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
|
16
|
+
if COMMANDS.include? command
|
17
|
+
args << '-h' if args.empty?
|
18
|
+
"DockerRailsProxy::#{command}".constantize.(arguments: args)
|
19
|
+
else
|
20
|
+
$stderr.puts <<-EOS
|
21
|
+
#{'No such command'.yellow}
|
22
|
+
|
23
|
+
#{'COMMANDS'.bold}
|
24
|
+
EOS
|
25
|
+
|
26
|
+
COMMANDS.each do |script|
|
27
|
+
$stderr.puts <<-EOS
|
28
|
+
#{script.parameterize.bold} [<args>]
|
29
|
+
EOS
|
30
|
+
end
|
31
|
+
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module DockerRailsProxy
|
4
|
+
class Build < Docker
|
5
|
+
attr_accessor :options
|
6
|
+
|
7
|
+
after_initialize { self.options = {} }
|
8
|
+
after_initialize :parse_options!
|
9
|
+
|
10
|
+
validates do
|
11
|
+
if options[:dockerfile].nil?
|
12
|
+
'--dockerfile is required'
|
13
|
+
elsif !File.exist?(options[:dockerfile])
|
14
|
+
"#{options[:dockerfile]} dockerfile does not exist."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
validates { '--tag is required' if options[:tag].nil? }
|
19
|
+
|
20
|
+
validates do
|
21
|
+
options[:build_args] ||= {}
|
22
|
+
|
23
|
+
args = File.readlines(options[:dockerfile]).map do |line|
|
24
|
+
/^ARG/ =~ line ? line.split(' ').last : nil
|
25
|
+
end.compact
|
26
|
+
|
27
|
+
missings = args.select { |arg| options[:build_args][arg].nil? }.compact
|
28
|
+
|
29
|
+
(options[:build_args].keys - args).each { |k| options[:build_args].delete k }
|
30
|
+
|
31
|
+
missings.map { |a| "#{a} is required" }.join(', ') unless missings.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
def process
|
35
|
+
system <<-EOS
|
36
|
+
docker build \
|
37
|
+
-f '#{options[:dockerfile]}' \
|
38
|
+
-t '#{options[:tag]}' \
|
39
|
+
#{build_args} \
|
40
|
+
'#{APP_PATH}'
|
41
|
+
EOS
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def build_args
|
47
|
+
options[:build_args].map do |k, v|
|
48
|
+
"--build-arg #{k.upcase}='#{v.strip}'"
|
49
|
+
end.join(' ')
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_options!
|
53
|
+
opt_parser.parse!(arguments)
|
54
|
+
end
|
55
|
+
|
56
|
+
def opt_parser
|
57
|
+
@opt_parser ||= OptionParser.new do |opts|
|
58
|
+
opts.banner = "Usage: bin/#{APP_NAME} build [options]"
|
59
|
+
|
60
|
+
opts.on('--dockerfile DOCKERFILE', 'Dockerfile') do |dockerfile|
|
61
|
+
options[:dockerfile] = dockerfile
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on('--tag TAG', 'Docker Image Tag') { |tag| options[:tag] = tag }
|
65
|
+
|
66
|
+
opts.on('--build-args A=val,B=val...', Array, 'Docker build-args') do |o|
|
67
|
+
options[:build_args] = Hash[o.map { |s| s.split('=', 2) }]
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on('-h', '--help', 'Display this screen') do
|
71
|
+
puts opts
|
72
|
+
exit
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
class Compose < Docker
|
3
|
+
class Down < self
|
4
|
+
def process
|
5
|
+
containers = %x(
|
6
|
+
docker-compose ps | grep '#{APP_NAME}' | awk '{print $1}' | xargs
|
7
|
+
).strip.split(' ')
|
8
|
+
|
9
|
+
system "docker stop #{containers.join(' ')}"
|
10
|
+
system "docker rm -v #{containers.join(' ')}"
|
11
|
+
system 'docker-compose down'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
class Compose < Docker
|
3
|
+
class Override < self
|
4
|
+
OVERRIDE_PATH = build_path('docker-compose.override.yml')
|
5
|
+
OVERRIDE_FILE = <<EOS.freeze
|
6
|
+
version: "2"
|
7
|
+
services:
|
8
|
+
app:
|
9
|
+
volumes:
|
10
|
+
- #{build_path(".data-bags/certs/localhost.#{APP_NAME}/cert.crt:/certs/cert.crt")}
|
11
|
+
- #{build_path(".data-bags/certs/localhost.#{APP_NAME}/cert.key:/certs/cert.key")}
|
12
|
+
EOS
|
13
|
+
|
14
|
+
def process
|
15
|
+
File.write(OVERRIDE_PATH, OVERRIDE_FILE)
|
16
|
+
puts "#{OVERRIDE_PATH} was created"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'pty'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module DockerRailsProxy
|
5
|
+
class Compose < Docker
|
6
|
+
class Up < self
|
7
|
+
FSWATCH_CMD = <<-EOS.strip.freeze
|
8
|
+
fswatch -r -0 \
|
9
|
+
--latency=0.1 \
|
10
|
+
--exclude '.git' \
|
11
|
+
--exclude '4913' \
|
12
|
+
"#{APP_PATH}" "#{GEMS_PATH}" | xargs -0 -n1 -I{} echo {}
|
13
|
+
EOS
|
14
|
+
|
15
|
+
EIO_ERROR = %(
|
16
|
+
Errno:EIO error, but this probably just means that the process
|
17
|
+
has finished giving output
|
18
|
+
).freeze
|
19
|
+
|
20
|
+
attr_accessor :branch_name, :stopping, :options, :from_scratch
|
21
|
+
|
22
|
+
alias_method :stopping?, :stopping
|
23
|
+
alias_method :from_scratch?, :from_scratch
|
24
|
+
|
25
|
+
before_initialize do
|
26
|
+
unless system 'type fswatch &> /dev/null'
|
27
|
+
'fswatch is required, `brew install fswatch`'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
after_initialize { self.options = {} }
|
32
|
+
after_initialize { self.branch_name = current_branch }
|
33
|
+
|
34
|
+
after_initialize :parse_options!, :set_defaults
|
35
|
+
|
36
|
+
before_process do
|
37
|
+
self.from_scratch = %x(docker-compose ps | grep -c #{APP_NAME}).to_i.zero?
|
38
|
+
end
|
39
|
+
|
40
|
+
after_process { fswatch_start }
|
41
|
+
|
42
|
+
def process
|
43
|
+
system 'docker-compose up -d'
|
44
|
+
sync_app_and_gems_folders
|
45
|
+
run_bundle_install if options[:bundle]
|
46
|
+
seed if from_scratch?
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def seed
|
52
|
+
system <<-EOS.strip.freeze
|
53
|
+
docker exec #{APP_NAME} bin/rake db:drop db:create db:migrate db:seed
|
54
|
+
EOS
|
55
|
+
end
|
56
|
+
|
57
|
+
def sync_app_and_gems_folders
|
58
|
+
rsync_app
|
59
|
+
sync source: GEMS_PATH
|
60
|
+
end
|
61
|
+
|
62
|
+
def rsync_app
|
63
|
+
loop do
|
64
|
+
break if sync(source: APP_PATH)
|
65
|
+
puts "waiting for rsync-volume service on #{rsync_host}"
|
66
|
+
sleep 2
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def fswatch_start
|
71
|
+
PTY.spawn(FSWATCH_CMD) do |stdout, stdin, pid|
|
72
|
+
begin
|
73
|
+
stdout.each { |path| sync_or_kill(path: path, pid: pid) }
|
74
|
+
rescue Errno::EIO
|
75
|
+
$stderr.puts EIO_ERROR
|
76
|
+
end
|
77
|
+
end
|
78
|
+
rescue PTY::ChildExited
|
79
|
+
$stderr.puts '"The fswatch process exited!'
|
80
|
+
end
|
81
|
+
|
82
|
+
def sync_or_kill(path:, pid:)
|
83
|
+
return if stopping?
|
84
|
+
|
85
|
+
if branch_name == (branch = current_branch)
|
86
|
+
sync source: path
|
87
|
+
else
|
88
|
+
$stderr.puts %(
|
89
|
+
`git checkout #{branch}` was detected, stopping fswatch
|
90
|
+
Previous branch was '#{branch_name}'
|
91
|
+
)
|
92
|
+
Process.kill(9, pid)
|
93
|
+
self.stopping = true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def current_branch
|
98
|
+
%x(git rev-parse --abbrev-ref HEAD).strip
|
99
|
+
end
|
100
|
+
|
101
|
+
# since new gems may have been added, we need bundle install
|
102
|
+
def run_bundle_install
|
103
|
+
system "docker exec #{APP_NAME} bundle install"
|
104
|
+
end
|
105
|
+
|
106
|
+
def parse_options!
|
107
|
+
opt_parser.parse!(arguments)
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_defaults
|
111
|
+
options[:bundle] = true if options[:bundle].nil?
|
112
|
+
end
|
113
|
+
|
114
|
+
def opt_parser
|
115
|
+
@opt_parser ||= OptionParser.new do |opts|
|
116
|
+
opts.banner = "Usage: bin/#{APP_NAME} compose up [options]"
|
117
|
+
|
118
|
+
opts.on(
|
119
|
+
'--[no-]bundle',
|
120
|
+
'Run bundle install in all related containers'
|
121
|
+
) { |bundle| options[:bundle] = bundle }
|
122
|
+
|
123
|
+
opts.on('-h', '--help', 'Display this screen') do
|
124
|
+
puts opts
|
125
|
+
exit
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
class Compose < Docker
|
3
|
+
autoload :Down, 'docker_rails_proxy/commands/compose/down'
|
4
|
+
autoload :Override, 'docker_rails_proxy/commands/compose/override'
|
5
|
+
autoload :Proxy, 'docker_rails_proxy/commands/compose/proxy'
|
6
|
+
autoload :Up, 'docker_rails_proxy/commands/compose/up'
|
7
|
+
|
8
|
+
builds -> (params:) do
|
9
|
+
case params[:arguments].first
|
10
|
+
when 'down' then Down
|
11
|
+
when 'override' then Override
|
12
|
+
when 'up' then Up
|
13
|
+
else
|
14
|
+
Proxy
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module DockerRailsProxy
|
4
|
+
class DataBags < AwsCli
|
5
|
+
attr_accessor :options
|
6
|
+
|
7
|
+
after_initialize { self.options = {} }
|
8
|
+
after_initialize :parse_options!, :set_defaults
|
9
|
+
|
10
|
+
before_process :set_folder_and_bucket
|
11
|
+
|
12
|
+
validates { '--profile is required.' if options[:profile].nil? }
|
13
|
+
validates { '--bucket is required.' if options[:bucket].nil? }
|
14
|
+
|
15
|
+
def process
|
16
|
+
case arguments.first
|
17
|
+
when 'pull' then pull
|
18
|
+
when 'push' then push
|
19
|
+
else
|
20
|
+
opt_parser.parse %w(-h)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def pull
|
27
|
+
if system <<-EOS.strip
|
28
|
+
aws s3 sync '#{options[:bucket]}' '#{options[:folder]}' \
|
29
|
+
--delete \
|
30
|
+
--exact-timestamps \
|
31
|
+
--profile '#{options[:profile]}'
|
32
|
+
EOS
|
33
|
+
|
34
|
+
puts "Data bags pulled from #{options[:bucket]} to #{options[:folder]}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def push
|
39
|
+
puts "#{options[:bucket]} will be synced with #{options[:folder]}, are you sure?: [yes]"
|
40
|
+
confirm = $stdin.gets.chomp
|
41
|
+
|
42
|
+
exit unless confirm == 'yes'
|
43
|
+
|
44
|
+
if system <<-EOS
|
45
|
+
aws s3 sync '#{options[:folder]}' '#{options[:bucket]}' \
|
46
|
+
--delete \
|
47
|
+
--exact-timestamps \
|
48
|
+
--profile '#{options[:profile]}' \
|
49
|
+
--sse aws:kms
|
50
|
+
EOS
|
51
|
+
|
52
|
+
puts "Data bags pushed from #{options[:folder]} to #{options[:bucket]}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_defaults
|
57
|
+
options[:profile] ||= APP_NAME
|
58
|
+
options[:bucket] ||= "#{APP_NAME}-data-bags"
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_folder_and_bucket
|
62
|
+
options[:folder] = build_path('.data-bags')
|
63
|
+
options[:bucket] = "s3://#{options[:bucket]}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_options!
|
67
|
+
opt_parser.parse!(arguments)
|
68
|
+
end
|
69
|
+
|
70
|
+
def opt_parser
|
71
|
+
@opt_parser ||= OptionParser.new do |opts|
|
72
|
+
opts.banner = "Usage: bin/#{APP_NAME} data-bags <pull|push> [options]"
|
73
|
+
|
74
|
+
opts.on(
|
75
|
+
'--profile [PROFILE]',
|
76
|
+
"Aws profile (Default: #{APP_NAME})"
|
77
|
+
) { |profile| options[:profile] = profile }
|
78
|
+
|
79
|
+
opts.on(
|
80
|
+
'--bucket [BUCKET]',
|
81
|
+
"AWS S3 Data bags bucket (Default: #{APP_NAME}-data-bags)"
|
82
|
+
) { |bucket| options[:bucket] = bucket }
|
83
|
+
|
84
|
+
opts.on('-h', '--help', 'Display this screen') do
|
85
|
+
puts opts
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
class Rails < SyncBack
|
3
|
+
def process
|
4
|
+
command, *args = arguments
|
5
|
+
|
6
|
+
case command
|
7
|
+
when 'c', 'console' then console args
|
8
|
+
when 'db', 'dbconsole' then db args
|
9
|
+
when 'logs' then logs args
|
10
|
+
when 'restart', 'touch' then restart
|
11
|
+
else
|
12
|
+
system "docker exec -it #{APP_NAME} bin/rails #{command} #{args.join(' ')}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def console(args)
|
19
|
+
exec "docker exec -it #{APP_NAME} bin/rails c #{args.join(' ')}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def db(args)
|
23
|
+
exec <<-EOS
|
24
|
+
docker exec -it #{APP_NAME}_db \
|
25
|
+
mysql #{args.first || "#{APP_NAME}_development"}
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
|
29
|
+
def logs(args)
|
30
|
+
exec <<-EOS
|
31
|
+
docker exec #{APP_NAME} tail -f log/#{args.first || 'development'}.log
|
32
|
+
EOS
|
33
|
+
end
|
34
|
+
|
35
|
+
def restart
|
36
|
+
exec "docker exec #{APP_NAME} touch tmp/restart.txt"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module DockerRailsProxy
|
4
|
+
class Ssh < DockerMainApp
|
5
|
+
def process
|
6
|
+
command, *args = arguments
|
7
|
+
|
8
|
+
case command
|
9
|
+
when '-h', '--help'
|
10
|
+
opt_parser.parse %w(-h)
|
11
|
+
else
|
12
|
+
system "docker exec -it #{APP_NAME} #{command} #{args.join(' ')}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def opt_parser
|
19
|
+
@opt_parser ||= OptionParser.new do |opts|
|
20
|
+
opts.banner = "Usage: bin/#{APP_NAME} ssh COMMAND [options]"
|
21
|
+
|
22
|
+
opts.on('-h', '--help', 'Display this screen') do
|
23
|
+
puts opts
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
module Callbacks
|
3
|
+
INHERITABLE_CALLBACKS = %w(
|
4
|
+
_before_initialize
|
5
|
+
_after_initialize
|
6
|
+
_validates
|
7
|
+
_before_process
|
8
|
+
_after_process
|
9
|
+
).freeze
|
10
|
+
|
11
|
+
UNINHERITABLE_CALLBACKS = %w(
|
12
|
+
_builds
|
13
|
+
).freeze
|
14
|
+
|
15
|
+
def self.included(base)
|
16
|
+
base.extend(ClassMethods)
|
17
|
+
|
18
|
+
INHERITABLE_CALLBACKS.each do |callback|
|
19
|
+
base.inheritable_attributes callback.to_sym
|
20
|
+
base.send "#{callback}=", []
|
21
|
+
end
|
22
|
+
|
23
|
+
UNINHERITABLE_CALLBACKS.each do |callback|
|
24
|
+
base.uninheritable_attributes callback.to_sym
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
private
|
30
|
+
|
31
|
+
INHERITABLE_CALLBACKS.each do |type|
|
32
|
+
define_method(type.sub('_', '').to_sym) do |*callbacks, &block|
|
33
|
+
_add_callbacks type: type, callbacks: callbacks, &block
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
UNINHERITABLE_CALLBACKS.each do |type|
|
38
|
+
define_method(type.sub('_', '').to_sym) do |*callbacks, &block|
|
39
|
+
send("#{type}=", []) if send(type).nil?
|
40
|
+
_add_callbacks type: type, callbacks: callbacks, &block
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def _add_callbacks(type:, callbacks:, &block)
|
45
|
+
callbacks.each { |c| send(type) << _make_lambda(callback: c) }
|
46
|
+
send(type) << _make_lambda(callback: block) if block_given?
|
47
|
+
send type
|
48
|
+
end
|
49
|
+
|
50
|
+
def _make_lambda(callback:)
|
51
|
+
case callback
|
52
|
+
when Symbol
|
53
|
+
-> (resource, *rest) { resource.send(callback, *rest) }
|
54
|
+
when ::Proc
|
55
|
+
if callback.arity <= 0
|
56
|
+
-> (resource) { resource.instance_exec(&callback) }
|
57
|
+
else
|
58
|
+
-> (resource, *rest) do
|
59
|
+
if rest.empty?
|
60
|
+
resource.instance_exec(resource, &callback)
|
61
|
+
else
|
62
|
+
resource.instance_exec(*rest, &callback)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
else
|
67
|
+
-> (*) {}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def _run_before_initialize_callbacks
|
72
|
+
Array(_before_initialize).each do |callback|
|
73
|
+
if (result = callback.call(self)).is_a? String
|
74
|
+
$stderr.puts %(
|
75
|
+
#{result}
|
76
|
+
)
|
77
|
+
exit 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def _run_after_initialize_callbacks(resource:)
|
83
|
+
Array(_after_initialize).each { |c| c.call(resource) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def _run_validation_callbacks(resource:)
|
87
|
+
Array(_validates).each do |callback|
|
88
|
+
if (result = callback.call(resource)).is_a? String
|
89
|
+
$stderr.puts %(
|
90
|
+
#{result}
|
91
|
+
)
|
92
|
+
exit 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def _run_before_process_callbacks(resource:)
|
98
|
+
Array(_before_process).each { |c| c.call(resource) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def _run_after_process_callbacks(resource:)
|
102
|
+
Array(_after_process).each { |c| c.call(resource) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def _run_build_callbacks(params:)
|
106
|
+
Array(_builds).each do |callback|
|
107
|
+
result = callback.call(self, params: params)
|
108
|
+
return result if result.is_a?(Class)
|
109
|
+
end
|
110
|
+
|
111
|
+
self
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
module InheritableAttributes
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def inheritable_attributes(*args)
|
9
|
+
@inheritable_attributes ||= [:inheritable_attributes]
|
10
|
+
@inheritable_attributes += args
|
11
|
+
args.each do |arg|
|
12
|
+
class_eval %(class << self; attr_accessor :#{arg} end)
|
13
|
+
end
|
14
|
+
@inheritable_attributes
|
15
|
+
end
|
16
|
+
|
17
|
+
def uninheritable_attributes(*args)
|
18
|
+
@uninheritable_attributes ||= [:uninheritable_attributes]
|
19
|
+
@uninheritable_attributes += args
|
20
|
+
args.each do |arg|
|
21
|
+
class_eval %(class << self; attr_accessor :#{arg} end)
|
22
|
+
end
|
23
|
+
@uninheritable_attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
def inherited(subclass)
|
27
|
+
@inheritable_attributes.each do |inheritable_attribute|
|
28
|
+
instance_name = "@#{inheritable_attribute}"
|
29
|
+
instance_value = instance_variable_get(instance_name).dup
|
30
|
+
subclass.instance_variable_set(instance_name, instance_value)
|
31
|
+
end
|
32
|
+
|
33
|
+
@uninheritable_attributes.each do |uninheritable_attribute|
|
34
|
+
instance_name = "@#{uninheritable_attribute}"
|
35
|
+
|
36
|
+
if instance_name == '@uninheritable_attributes'
|
37
|
+
instance_value = instance_variable_get(instance_name).dup
|
38
|
+
subclass.instance_variable_set(instance_name, instance_value)
|
39
|
+
else
|
40
|
+
subclass.instance_variable_set(instance_name, nil)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module DockerRailsProxy
|
2
|
+
module Rsync
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
def sync(source:, reverse: false, silent: false)
|
11
|
+
_rsync.sync source: source, reverse: reverse, silent: silent
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def _rsync_host
|
17
|
+
@_rsync_host ||= begin
|
18
|
+
"rsync://#{ENV['DOCKER_HOST'].to_s.sub('tcp://', '').sub(/:\d+$/, '')}:10873"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def _rsync
|
23
|
+
@_rsync ||= Sync.new(rsync_host: _rsync_host)
|
24
|
+
end
|
25
|
+
|
26
|
+
class Sync
|
27
|
+
attr_reader :rsync_host
|
28
|
+
|
29
|
+
def initialize(rsync_host:)
|
30
|
+
@rsync_host = rsync_host
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.call(rsync_host:, **options)
|
34
|
+
new(rsync_host: rsync_host).sync(options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def sync(options)
|
38
|
+
source, target, volume = normalize_options(options)
|
39
|
+
|
40
|
+
result = send "sync_#{volume}", source: source, target: target
|
41
|
+
|
42
|
+
if result && options[:silent].eql?(false)
|
43
|
+
puts "#{source} =======> #{target}"
|
44
|
+
end
|
45
|
+
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def normalize_options(source:, reverse: false, **)
|
52
|
+
values = if source.include? APP_PATH
|
53
|
+
["#{APP_PATH}/", 'app']
|
54
|
+
elsif source.include? GEMS_PATH
|
55
|
+
["#{GEMS_PATH}/", 'gems']
|
56
|
+
else
|
57
|
+
$stderr.puts "There is no rsync volume related with this path: #{source}"
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
|
61
|
+
paths = [values.first, "#{rsync_host}/#{values.last}"]
|
62
|
+
|
63
|
+
[paths.send(reverse ? :reverse : :to_a), values.last].flatten
|
64
|
+
end
|
65
|
+
|
66
|
+
def sync_app(source:, target:)
|
67
|
+
system <<-EOS
|
68
|
+
rsync -avqP --no-owner --no-group \
|
69
|
+
--exclude 'tmp/cache' \
|
70
|
+
--exclude 'tmp/letter_opener' \
|
71
|
+
--exclude 'tmp/pids' \
|
72
|
+
--exclude 'log' \
|
73
|
+
--exclude '.git*' \
|
74
|
+
--force \
|
75
|
+
--delete \
|
76
|
+
#{source} #{target}
|
77
|
+
EOS
|
78
|
+
end
|
79
|
+
|
80
|
+
def sync_gems(source:, target:)
|
81
|
+
system <<-EOS
|
82
|
+
rsync -avqP --no-owner --no-group \
|
83
|
+
--exclude '.git*' \
|
84
|
+
--force \
|
85
|
+
--delete \
|
86
|
+
#{source} #{target}
|
87
|
+
EOS
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class String
|
2
|
+
def red
|
3
|
+
colorize(31)
|
4
|
+
end
|
5
|
+
|
6
|
+
def green
|
7
|
+
colorize(32)
|
8
|
+
end
|
9
|
+
|
10
|
+
def yellow
|
11
|
+
colorize(33)
|
12
|
+
end
|
13
|
+
|
14
|
+
def blue
|
15
|
+
colorize(34)
|
16
|
+
end
|
17
|
+
|
18
|
+
def pink
|
19
|
+
colorize(35)
|
20
|
+
end
|
21
|
+
|
22
|
+
def light_blue
|
23
|
+
colorize(36)
|
24
|
+
end
|
25
|
+
|
26
|
+
def bold
|
27
|
+
"\033[1m#{self}\033[0m"
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# colorization
|
33
|
+
def colorize(color_code)
|
34
|
+
"\e[#{color_code}m#{self}\e[0m"
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class String
|
2
|
+
def parameterize(separator = '-'.freeze)
|
3
|
+
downcase.gsub(/\W/, separator).gsub('_'.freeze, separator)
|
4
|
+
end
|
5
|
+
|
6
|
+
def classify
|
7
|
+
gsub(/\W/, ''.freeze)
|
8
|
+
.gsub('_'.freeze, ''.freeze)
|
9
|
+
.sub(/^[a-z\d]*/, &:capitalize)
|
10
|
+
end
|
11
|
+
|
12
|
+
def constantize
|
13
|
+
split('::'.freeze).inject(Object) do |constant, name|
|
14
|
+
constant.const_get(name.classify)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def underscore
|
19
|
+
downcase.gsub('::'.freeze, '/'.freeze).gsub('-'.freeze, '_'.freeze)
|
20
|
+
end
|
21
|
+
end
|
data/lib/docker_rails_proxy.rb
CHANGED
@@ -1,2 +1,105 @@
|
|
1
|
+
require 'docker_rails_proxy/extends/colorization'
|
2
|
+
require 'docker_rails_proxy/extends/string_support'
|
3
|
+
|
1
4
|
module DockerRailsProxy
|
5
|
+
COMMANDS = Dir[File.expand_path('../docker_rails_proxy/commands/*.rb', __FILE__)].map do |f|
|
6
|
+
File.basename(f, '.rb').parameterize
|
7
|
+
end.freeze
|
8
|
+
|
9
|
+
COMMANDS.each do |c|
|
10
|
+
autoload c.classify.to_sym, "docker_rails_proxy/commands/#{c.underscore}"
|
11
|
+
end
|
12
|
+
|
13
|
+
autoload :InheritableAttributes, 'docker_rails_proxy/concerns/inheritable_attributes'
|
14
|
+
autoload :Callbacks, 'docker_rails_proxy/concerns/callbacks'
|
15
|
+
autoload :Rsync, 'docker_rails_proxy/concerns/rsync'
|
16
|
+
|
17
|
+
autoload :Cli, 'docker_rails_proxy/cli'
|
18
|
+
autoload :VERSION, 'docker_rails_proxy/version'
|
19
|
+
|
20
|
+
class Base
|
21
|
+
include InheritableAttributes
|
22
|
+
include Callbacks
|
23
|
+
include Rsync
|
24
|
+
|
25
|
+
attr_reader :arguments
|
26
|
+
|
27
|
+
def initialize(arguments:)
|
28
|
+
@arguments = arguments
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def build_path(path = nil)
|
33
|
+
File.join(APP_PATH, block_given? ? yield : path)
|
34
|
+
end
|
35
|
+
|
36
|
+
def call(options)
|
37
|
+
klass = _run_build_callbacks params: options
|
38
|
+
|
39
|
+
klass.send :_run_before_initialize_callbacks
|
40
|
+
|
41
|
+
resource = klass.new(options)
|
42
|
+
|
43
|
+
klass.send :_run_after_initialize_callbacks, resource: resource
|
44
|
+
|
45
|
+
klass.send :_run_validation_callbacks, resource: resource
|
46
|
+
|
47
|
+
klass.send :_run_before_process_callbacks, resource: resource
|
48
|
+
|
49
|
+
result = resource.process
|
50
|
+
|
51
|
+
klass.send :_run_after_process_callbacks, resource: resource
|
52
|
+
result
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def process
|
57
|
+
raise NotImplementedError, 'Subclasses must implement a process method'
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def build_path(*args, &block)
|
63
|
+
self.class.build_path(*args, &block)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class AwsCli < Base
|
68
|
+
before_initialize do
|
69
|
+
unless system 'type aws &> /dev/null'
|
70
|
+
'aws is required, `brew install awscli`'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Docker < Base
|
76
|
+
before_initialize do
|
77
|
+
if ENV['DOCKER_HOST'].nil?
|
78
|
+
%(
|
79
|
+
Couldn't connect to Docker daemon you might need to run:
|
80
|
+
docker-machine start default
|
81
|
+
eval $(docker-machine env default)
|
82
|
+
)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class DockerMainApp < Docker
|
88
|
+
before_initialize do
|
89
|
+
unless system "docker ps | grep '#{APP_NAME}$' &> /dev/null"
|
90
|
+
%(
|
91
|
+
Couldn't connect to #{APP_NAME} container you might need to run:
|
92
|
+
bin/#{APP_NAME} compose up
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Makes sure the container is in sync with the APP_PATH
|
98
|
+
before_process { sync source: APP_PATH, silent: true }
|
99
|
+
end
|
100
|
+
|
101
|
+
class SyncBack < DockerMainApp
|
102
|
+
after_process { system "docker exec #{APP_NAME} chown -R nobody:nogroup ." }
|
103
|
+
after_process { sync source: APP_PATH, reverse: true }
|
104
|
+
end
|
2
105
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docker_rails_proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jairo
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-09-
|
12
|
+
date: 2016-09-30 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Configures docker-compose and provides rails command helpers
|
15
15
|
email:
|
@@ -22,6 +22,26 @@ files:
|
|
22
22
|
- MIT-LICENSE
|
23
23
|
- README.md
|
24
24
|
- lib/docker_rails_proxy.rb
|
25
|
+
- lib/docker_rails_proxy/cli.rb
|
26
|
+
- lib/docker_rails_proxy/commands/build.rb
|
27
|
+
- lib/docker_rails_proxy/commands/bundle.rb
|
28
|
+
- lib/docker_rails_proxy/commands/compose.rb
|
29
|
+
- lib/docker_rails_proxy/commands/compose/down.rb
|
30
|
+
- lib/docker_rails_proxy/commands/compose/override.rb
|
31
|
+
- lib/docker_rails_proxy/commands/compose/proxy.rb
|
32
|
+
- lib/docker_rails_proxy/commands/compose/up.rb
|
33
|
+
- lib/docker_rails_proxy/commands/data_bags.rb
|
34
|
+
- lib/docker_rails_proxy/commands/rails.rb
|
35
|
+
- lib/docker_rails_proxy/commands/rake.rb
|
36
|
+
- lib/docker_rails_proxy/commands/rspec.rb
|
37
|
+
- lib/docker_rails_proxy/commands/spring.rb
|
38
|
+
- lib/docker_rails_proxy/commands/ssh.rb
|
39
|
+
- lib/docker_rails_proxy/concerns/callbacks.rb
|
40
|
+
- lib/docker_rails_proxy/concerns/inheritable_attributes.rb
|
41
|
+
- lib/docker_rails_proxy/concerns/rsync.rb
|
42
|
+
- lib/docker_rails_proxy/extends/colorization.rb
|
43
|
+
- lib/docker_rails_proxy/extends/string_support.rb
|
44
|
+
- lib/docker_rails_proxy/version.rb
|
25
45
|
homepage: https://github.com/jairovm/docker_rails_proxy
|
26
46
|
licenses:
|
27
47
|
- MIT
|