vader 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +32 -0
- data/Rakefile +2 -0
- data/bin/vader +3 -0
- data/lib/vader/exec.rb +19 -0
- data/lib/vader/sync.rb +160 -0
- data/lib/vader/version.rb +3 -0
- data/lib/vader.rb +40 -0
- data/libexec/setup +58 -0
- data/src/launchctl.plist.erb +31 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e03240a14c0f4c941b9a061c058d91320e765937
|
4
|
+
data.tar.gz: 3435b024b83438dc360c1939a6a4871a5a601af2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 33309382526388905cb0f448e1c9f200f5d2b0d8a376a66b3ac0938711fae6e1ffdfd080b8a460e83d4c4c322c1d01ce71503153c4ff4e699da7f48c4f58c62f
|
7
|
+
data.tar.gz: 32abc280d0e053e1d702efd0d8a7caadeece0a2a2f6b46f15cbd9bf105e97722af55fea92260bdfe97dc96744a8c4f9377f514e2d7a4b85f594201f735c0bfdb
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# vader
|
2
|
+
Vader: Apple Docker Environment for Rails
|
3
|
+
|
4
|
+
## Commands
|
5
|
+
|
6
|
+
Install vader: `curl get.vader.codes | bash -e`
|
7
|
+
|
8
|
+
`vader init` - configures current directory for vader
|
9
|
+
|
10
|
+
`vader sync` - starts rsync daemon, usually called by startup script
|
11
|
+
|
12
|
+
`vader sync-back` - called after `rails g`, `bundle`
|
13
|
+
|
14
|
+
`vader exec ...`
|
15
|
+
|
16
|
+
`vader up`
|
17
|
+
|
18
|
+
`vader -v`
|
19
|
+
`vader help`
|
20
|
+
|
21
|
+
# Config:
|
22
|
+
`.vader.yml`:
|
23
|
+
```
|
24
|
+
min_version: 123 # Minimum required vader version
|
25
|
+
exec_container: app
|
26
|
+
```
|
27
|
+
|
28
|
+
|
29
|
+
# NB: user gem install:
|
30
|
+
```
|
31
|
+
gem install --user-install --bindir /usr/local/bin vader-0.0.1.gem
|
32
|
+
```
|
data/Rakefile
ADDED
data/bin/vader
ADDED
data/lib/vader/exec.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class Vader::Exec
|
2
|
+
|
3
|
+
def run
|
4
|
+
command = [
|
5
|
+
"docker", "exec", "-ti", container,
|
6
|
+
# Set TERM for colors 🌈
|
7
|
+
"env", "TERM=#{ENV['TERM']}"
|
8
|
+
] + ARGV
|
9
|
+
|
10
|
+
puts "Executing #{command.inspect}" if ENV['VADER_VERBOSE']
|
11
|
+
exec(*command)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def container
|
16
|
+
"#{File.basename(Dir.pwd)}_app_1"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/lib/vader/sync.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
class Vader::Sync
|
2
|
+
require 'shellwords'
|
3
|
+
|
4
|
+
B2D_BIN = '/usr/local/bin/boot2docker'
|
5
|
+
B2D_ROOT = ENV['VADER_B2D_ROOT'] || "/vader"
|
6
|
+
CONFIG_DIR = File.expand_path(ENV['VADER_CONFIG_DIR'] || '~/.vader')
|
7
|
+
SYNC_LATENCY = (ENV['VADER_SYNC_LATENCY'] || 0.1).to_f
|
8
|
+
|
9
|
+
# Hash of local paths and boot2docker destination
|
10
|
+
attr_reader :watch_paths
|
11
|
+
# Array of local paths
|
12
|
+
attr_reader :local_watch_paths
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
glob = File.join(CONFIG_DIR, '*')
|
16
|
+
|
17
|
+
# A hash of paths to watch and their boot2docker destinations
|
18
|
+
# E.g.
|
19
|
+
# { '/Users/alice/Documents/my-project' => '/vader/my-project' }
|
20
|
+
@watch_paths = Dir.glob(glob).inject({}) { |hash, config_path|
|
21
|
+
b2d_path = File.join(B2D_ROOT, File.basename(config_path))
|
22
|
+
|
23
|
+
begin
|
24
|
+
watch_path = File.readlink(config_path)
|
25
|
+
hash.merge(watch_path => b2d_path)
|
26
|
+
rescue Errno::EINVAL
|
27
|
+
hash
|
28
|
+
end
|
29
|
+
}
|
30
|
+
|
31
|
+
@local_watch_paths = @watch_paths.keys
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def run
|
36
|
+
# Make sure boot2docker is running
|
37
|
+
waiting = false
|
38
|
+
while `#{B2D_BIN} status`.chomp != 'running'
|
39
|
+
puts "Waiting until boot2docker is running" unless waiting
|
40
|
+
waiting = true
|
41
|
+
sleep 2
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# Initialize boot2docker for vader
|
46
|
+
cmds = [
|
47
|
+
'tce-load -wi rsync', # Install rsync
|
48
|
+
# Make vader destination and symlink to /vader
|
49
|
+
'sudo mkdir -p /mnt/sda1/vader',
|
50
|
+
'sudo ln -sf /mnt/sda1/vader /',
|
51
|
+
'sudo chown docker:staff /vader'
|
52
|
+
]
|
53
|
+
|
54
|
+
safe_paths = @watch_paths.values.map{|path| Shellwords.shellescape(path)}.join(' ')
|
55
|
+
cmds << "mkdir -p #{safe_paths}" unless safe_paths.empty?
|
56
|
+
cmds = cmds.join(' && ')
|
57
|
+
|
58
|
+
puts "Running #{cmds}" if verbose?
|
59
|
+
`ssh #{boot2docker_ssh_options} #{boot2docker_ssh_host} "#{cmds}"`
|
60
|
+
|
61
|
+
unless $?.success?
|
62
|
+
puts "Error initalizing boot2docker for vader"
|
63
|
+
exit 1
|
64
|
+
end
|
65
|
+
|
66
|
+
# Watch for fs changes
|
67
|
+
puts "Watching #{local_watch_paths.inspect} + #{CONFIG_DIR}" if verbose?
|
68
|
+
fsevent = FSEvent.new
|
69
|
+
fsevent.watch local_watch_paths + [CONFIG_DIR], latency: SYNC_LATENCY do |paths|
|
70
|
+
handle_fs_event(paths)
|
71
|
+
end
|
72
|
+
fsevent.run
|
73
|
+
end
|
74
|
+
|
75
|
+
def handle_fs_event(full_paths)
|
76
|
+
puts "handling event for #{full_paths.inspect}" if verbose?
|
77
|
+
|
78
|
+
# full_paths is potentially large, so try to iterated efficiently
|
79
|
+
matched_paths = []
|
80
|
+
full_paths.each do |full_path|
|
81
|
+
# Skip if we've already mathed this path
|
82
|
+
next if matched_paths.any? {|p| full_path.start_with?(p) }
|
83
|
+
|
84
|
+
matched_path = local_watch_paths.detect{|p| full_path.start_with?(p) }
|
85
|
+
matched_paths << matched_path if matched_path
|
86
|
+
|
87
|
+
if full_path.start_with? CONFIG_DIR
|
88
|
+
puts "Vader config change detected, restarting."
|
89
|
+
exit 0
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
matched_paths.each {|path| sync(path) }
|
94
|
+
end
|
95
|
+
|
96
|
+
def sync(path)
|
97
|
+
puts "Syncing #{path}"
|
98
|
+
exclude_path = File.join(path, '.rsync-excludes')
|
99
|
+
|
100
|
+
rsync_options = [
|
101
|
+
'-av',
|
102
|
+
'--delete',
|
103
|
+
"--rsh=ssh #{boot2docker_ssh_options}"
|
104
|
+
]
|
105
|
+
|
106
|
+
if File.exists?(exclude_path)
|
107
|
+
rsync_options << "--exclude-from=#{exclude_path}"
|
108
|
+
end
|
109
|
+
|
110
|
+
rsync_options += [
|
111
|
+
"#{path}/",
|
112
|
+
"#{boot2docker_ssh_host}:#{watch_paths[path]}"
|
113
|
+
]
|
114
|
+
|
115
|
+
puts rsync_options.inspect if verbose?
|
116
|
+
options = verbose? ? {} : {out: '/dev/null'}
|
117
|
+
|
118
|
+
start = Time.now
|
119
|
+
pid = spawn("rsync", *rsync_options, options)
|
120
|
+
|
121
|
+
Process.wait(pid)
|
122
|
+
puts "Finished in #{Time.now - start} seconds" if verbose?
|
123
|
+
|
124
|
+
unless $?.success?
|
125
|
+
puts "Error syncing #{path}, restarting."
|
126
|
+
exit 1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def verbose?
|
131
|
+
ENV['VADER_VERBOSE']
|
132
|
+
end
|
133
|
+
|
134
|
+
def boot2docker_config
|
135
|
+
@boot2docker_config ||= `#{B2D_BIN} config`.split("\n").inject({}) {|hash, line|
|
136
|
+
match = line.match(/(?<key>\S+)\s=\s"?(?<value>[^\s"]+)"?/)
|
137
|
+
if match
|
138
|
+
hash.merge(match[:key] => match[:value])
|
139
|
+
else
|
140
|
+
hash
|
141
|
+
end
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def boot2docker_ssh_options
|
146
|
+
# From http://git.io/vJhs2
|
147
|
+
[
|
148
|
+
"-o", "IdentitiesOnly=yes",
|
149
|
+
"-o", "StrictHostKeyChecking=no",
|
150
|
+
"-o", "UserKnownHostsFile=/dev/null",
|
151
|
+
"-o", "LogLevel=quiet",
|
152
|
+
"-p", boot2docker_config['SSHPort'],
|
153
|
+
"-i", boot2docker_config['SSHKey']
|
154
|
+
].join(' ')
|
155
|
+
end
|
156
|
+
|
157
|
+
def boot2docker_ssh_host
|
158
|
+
"docker@localhost"
|
159
|
+
end
|
160
|
+
end
|
data/lib/vader.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
gem 'rb-fsevent', '0.9.4'
|
4
|
+
require 'rb-fsevent'
|
5
|
+
|
6
|
+
class Vader
|
7
|
+
autoload :VERSION, 'vader/version'
|
8
|
+
autoload :Sync, 'vader/sync'
|
9
|
+
autoload :Exec, 'vader/exec'
|
10
|
+
|
11
|
+
def run
|
12
|
+
check_version
|
13
|
+
|
14
|
+
case ARGV.shift
|
15
|
+
when 'sync'
|
16
|
+
Vader::Sync.new.run
|
17
|
+
when 'setup'
|
18
|
+
setup_path = File.expand_path('../libexec/setup', File.dirname(__FILE__))
|
19
|
+
exec setup_path
|
20
|
+
when 'init'
|
21
|
+
# Writeme
|
22
|
+
puts 'Not implemented yet. This will configure the current directory as a vader app'
|
23
|
+
when 'exec'
|
24
|
+
Vader::Exec.new.run
|
25
|
+
when 'up'
|
26
|
+
dc = '/usr/local/bin/docker-compose'
|
27
|
+
exec "#{dc} up -d && #{dc} logs app"
|
28
|
+
else
|
29
|
+
# TODO: Print help
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def check_version
|
35
|
+
unless 'darwin' == Gem::Platform.local.os
|
36
|
+
$stderr.puts "Error: vader only supports OS X"
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/libexec/setup
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/bin/bash -e
|
2
|
+
|
3
|
+
##
|
4
|
+
# Configure vader:
|
5
|
+
# - install system dependencies
|
6
|
+
# - install launchctl process
|
7
|
+
|
8
|
+
# Pretty colors
|
9
|
+
red=`tput setaf 1`
|
10
|
+
green=`tput setaf 2`
|
11
|
+
reset=`tput sgr0`
|
12
|
+
|
13
|
+
die() {
|
14
|
+
echo "${red}${1}${reset}"
|
15
|
+
exit 1
|
16
|
+
}
|
17
|
+
|
18
|
+
say() {
|
19
|
+
echo "${green}${1}${reset}"
|
20
|
+
}
|
21
|
+
|
22
|
+
##
|
23
|
+
# Install pow
|
24
|
+
if ! curl -sH host:pow 127.0.0.1/status.json > /dev/null
|
25
|
+
then
|
26
|
+
say "Installing pow"
|
27
|
+
curl get.pow.cx | bash
|
28
|
+
fi
|
29
|
+
|
30
|
+
##
|
31
|
+
# Install boot2docker
|
32
|
+
if ! /usr/local/bin/boot2docker -v >/dev/null 2>/dev/null
|
33
|
+
then
|
34
|
+
say "Installing boot2docker"
|
35
|
+
URL='https://github.com/boot2docker/osx-installer/releases/download/v1.6.0/Boot2Docker-1.6.0.pkg'
|
36
|
+
PKG=/tmp/boot2docker.pkg
|
37
|
+
curl -L -o $PKG $URL
|
38
|
+
|
39
|
+
sudo installer -pkg $PKG -target /
|
40
|
+
rm -f $PKG
|
41
|
+
fi
|
42
|
+
|
43
|
+
/usr/local/bin/boot2docker init > /dev/null
|
44
|
+
|
45
|
+
# Install docker-compose
|
46
|
+
if [ ! -x /usr/local/bin/docker-compose ]
|
47
|
+
then
|
48
|
+
say "Installing docker-compose"
|
49
|
+
curl -s -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
|
50
|
+
chmod +x /usr/local/bin/docker-compose
|
51
|
+
fi
|
52
|
+
|
53
|
+
mkdir -p ~/Library/Logs/Vader
|
54
|
+
/usr/bin/erb < `dirname $0`/../src/launchctl.plist.erb > "$HOME/Library/LaunchAgents/vader.sync.plist"
|
55
|
+
launchctl load -Fw "$HOME/Library/LaunchAgents/vader.sync.plist" 2>/dev/null
|
56
|
+
launchctl kickstart -k gui/"$UID"/vader.sync 2>/dev/null
|
57
|
+
|
58
|
+
say "Vader setup complete"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Label</key>
|
6
|
+
<string>vader.sync</string>
|
7
|
+
<key>ProgramArguments</key>
|
8
|
+
<array>
|
9
|
+
<string>/usr/local/bin/vader</string>
|
10
|
+
<string>sync</string>
|
11
|
+
</array>
|
12
|
+
|
13
|
+
<key>KeepAlive</key>
|
14
|
+
<true/>
|
15
|
+
<key>RunAtLoad</key>
|
16
|
+
<true/>
|
17
|
+
|
18
|
+
<key>StandardErrorPath</key>
|
19
|
+
<string><%= ENV['HOME'] %>/Library/Logs/Vader/sync.error.log</string>
|
20
|
+
<key>StandardOutPath</key>
|
21
|
+
<string><%= ENV['HOME'] %>/Library/Logs/Vader/sync.log</string>
|
22
|
+
|
23
|
+
<% if ENV['VADER_VERBOSE'] %>
|
24
|
+
<key>EnvironmentVariables</key>
|
25
|
+
<dict>
|
26
|
+
<key>VADER_VERBOSE</key>
|
27
|
+
<string><%= ENV['VADER_VERBOSE'] %></string>
|
28
|
+
</dict>
|
29
|
+
<% end %>
|
30
|
+
</dict>
|
31
|
+
</plist>
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vader
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aaron Suggs
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rb-fsevent
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.9.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: 'Vader: Apple Docker Environment for Rails'
|
56
|
+
email: aaron@ktheory.com
|
57
|
+
executables:
|
58
|
+
- vader
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- bin/vader
|
63
|
+
- libexec/setup
|
64
|
+
- lib/vader/exec.rb
|
65
|
+
- lib/vader/sync.rb
|
66
|
+
- lib/vader/version.rb
|
67
|
+
- lib/vader.rb
|
68
|
+
- src/launchctl.plist.erb
|
69
|
+
- Rakefile
|
70
|
+
- README.md
|
71
|
+
homepage: https://github.com/kickstarter/vader
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options:
|
77
|
+
- --charset=UTF-8
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 2.0.0
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.0.14
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Easily manage Docker containers for Rails apps on OS X
|
96
|
+
test_files: []
|