vader 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 +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: []
|