vader 0.0.1

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