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 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
@@ -0,0 +1,2 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
data/bin/vader ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/ruby
2
+ require 'vader'
3
+ Vader.new.run
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
@@ -0,0 +1,3 @@
1
+ class Vader
2
+ VERSION = '0.0.1'
3
+ 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: []