docker-sync 0.2.3 → 0.3.0
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/VERSION +1 -1
- data/lib/docker-sync.rb +4 -0
- data/lib/docker-sync/config/config_locator.rb +80 -0
- data/lib/docker-sync/config/config_serializer.rb +56 -0
- data/lib/docker-sync/config/global_config.rb +55 -0
- data/lib/docker-sync/config/project_config.rb +123 -0
- data/lib/docker-sync/preconditions/preconditions_linux.rb +24 -0
- data/lib/docker-sync/preconditions/preconditions_osx.rb +148 -0
- data/lib/docker-sync/preconditions/strategy.rb +57 -0
- data/lib/docker-sync/sync_manager.rb +16 -47
- data/lib/docker-sync/sync_process.rb +14 -22
- data/lib/docker-sync/sync_strategy/rsync.rb +3 -3
- data/lib/docker-sync/sync_strategy/unison.rb +3 -5
- data/lib/docker-sync/update_check.rb +18 -15
- data/lib/docker-sync/upgrade_check.rb +25 -7
- data/lib/docker-sync/watch_strategy/dummy.rb +0 -1
- data/lib/docker-sync/watch_strategy/fswatch.rb +2 -2
- data/lib/docker-sync/watch_strategy/unison.rb +0 -1
- data/tasks/daemon/daemon.thor +2 -2
- data/tasks/stack/stack.thor +12 -30
- data/tasks/sync/sync.thor +46 -28
- metadata +24 -5
- data/lib/docker-sync/config.rb +0 -120
- data/lib/docker-sync/config_template.rb +0 -17
- data/lib/docker-sync/preconditions.rb +0 -100
data/tasks/sync/sync.thor
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
require 'docker-sync'
|
1
2
|
require 'docker-sync/sync_manager'
|
2
|
-
require 'docker-sync/
|
3
|
-
require 'docker-sync/preconditions'
|
3
|
+
require 'docker-sync/preconditions/strategy'
|
4
4
|
require 'docker-sync/update_check'
|
5
5
|
require 'docker-sync/upgrade_check'
|
6
6
|
require 'daemons'
|
7
7
|
require 'fileutils'
|
8
|
+
require 'docker-sync/config/project_config'
|
9
|
+
require 'timeout'
|
8
10
|
|
9
11
|
class Sync < Thor
|
10
12
|
|
@@ -27,11 +29,11 @@ class Sync < Thor
|
|
27
29
|
def start
|
28
30
|
print_version if options[:version]
|
29
31
|
# do run update check in the start command only
|
30
|
-
UpdateChecker.new
|
31
|
-
UpgradeChecker.new
|
32
|
+
UpdateChecker.new.run
|
33
|
+
UpgradeChecker.new.run
|
32
34
|
|
33
|
-
|
34
|
-
@sync_manager = Docker_sync::SyncManager.new(:
|
35
|
+
config = config_preconditions
|
36
|
+
@sync_manager = Docker_sync::SyncManager.new(config: config)
|
35
37
|
|
36
38
|
start_dir = Dir.pwd # Set start_dir variable to be equal to pre-daemonized folder, since daemonizing will change dir to '/'
|
37
39
|
if options['daemon']
|
@@ -52,18 +54,17 @@ class Sync < Thor
|
|
52
54
|
def stop
|
53
55
|
print_version if options[:version]
|
54
56
|
|
55
|
-
|
56
|
-
sync_manager = Docker_sync::SyncManager.new(:
|
57
|
+
config = config_preconditions
|
58
|
+
sync_manager = Docker_sync::SyncManager.new(config: config)
|
57
59
|
|
58
60
|
begin
|
59
61
|
pid = File.read("#{options['dir']}/#{options['app_name']}.pid") # Read PID from PIDFILE created by Daemons
|
60
62
|
Process.kill(:INT, -(Process.getpgid(pid.to_i))) # Send INT signal to group PID, which means INT will be sent to all sub-processes and Threads spawned by docker-sync
|
61
|
-
|
63
|
+
wait_for_process_termination(pid.to_i)
|
62
64
|
rescue Errno::ESRCH, Errno::ENOENT => e
|
63
65
|
say_status 'error', e.message, :red # Rescue incase PIDFILE does not exist or there is no process with such PID
|
64
|
-
say_status
|
65
|
-
|
66
|
-
)
|
66
|
+
say_status 'error', 'Check if your PIDFILE and process with such PID exists', :red
|
67
|
+
exit(69) # EX_UNAVAILABLE (see `man sysexits` or `/usr/include/sysexits.h`)
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
@@ -71,9 +72,9 @@ class Sync < Thor
|
|
71
72
|
def sync
|
72
73
|
print_version if options[:version]
|
73
74
|
|
74
|
-
|
75
|
+
config = config_preconditions
|
75
76
|
|
76
|
-
@sync_manager = Docker_sync::SyncManager.new(:
|
77
|
+
@sync_manager = Docker_sync::SyncManager.new(config: config)
|
77
78
|
@sync_manager.sync(options[:sync_name])
|
78
79
|
end
|
79
80
|
|
@@ -81,7 +82,7 @@ class Sync < Thor
|
|
81
82
|
def clean
|
82
83
|
print_version if options[:version]
|
83
84
|
|
84
|
-
|
85
|
+
config = config_preconditions
|
85
86
|
|
86
87
|
# Look for any background syncs and stop them if we see them
|
87
88
|
dir = './.docker-sync'
|
@@ -94,7 +95,7 @@ class Sync < Thor
|
|
94
95
|
# Remove the .docker-sync directory
|
95
96
|
FileUtils.rm_r dir if File.directory?(dir)
|
96
97
|
|
97
|
-
@sync_manager = Docker_sync::SyncManager.new(:
|
98
|
+
@sync_manager = Docker_sync::SyncManager.new(config: config)
|
98
99
|
@sync_manager.clean(options[:sync_name])
|
99
100
|
say_status 'success', 'Finished cleanup. Removed stopped, removed sync container and removed their volumes', :green
|
100
101
|
end
|
@@ -116,10 +117,10 @@ class Sync < Thor
|
|
116
117
|
def list
|
117
118
|
print_version if options[:version]
|
118
119
|
|
119
|
-
|
120
|
+
config = config_preconditions
|
120
121
|
|
121
122
|
say_status 'ok',"Found configuration at #{config_path}"
|
122
|
-
@sync_manager = Docker_sync::SyncManager.new(:
|
123
|
+
@sync_manager = Docker_sync::SyncManager.new(config: config)
|
123
124
|
@sync_manager.get_sync_points.each do |name, config|
|
124
125
|
say_status name, "On address #{config['sync_host_ip']}:#{config['sync_host_port']}",:white unless options['verbose']
|
125
126
|
puts "\n---------------[#{name}] #{config['sync_host_ip']}:#{config['sync_host_port']} ---------------\n" if options['verbose']
|
@@ -130,16 +131,9 @@ class Sync < Thor
|
|
130
131
|
no_tasks do
|
131
132
|
def config_preconditions # Moved shared preconditions block into separate method to have less/cleaner code
|
132
133
|
begin
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
exit 1
|
137
|
-
end
|
138
|
-
|
139
|
-
return options[:config] if options[:config]
|
140
|
-
|
141
|
-
begin
|
142
|
-
DockerSyncConfig::project_config_path
|
134
|
+
DockerSync::ProjectConfig.new(config_path: options[:config]).tap do |config|
|
135
|
+
DockerSync::Preconditions::Strategy.instance.check_all_preconditions(config)
|
136
|
+
end
|
143
137
|
rescue Exception => e
|
144
138
|
say_status 'error', e.message, :red
|
145
139
|
exit 1
|
@@ -191,5 +185,29 @@ class Sync < Thor
|
|
191
185
|
pid_file = Daemons::PidFile.find_files(options['dir'], options['app_name']).first || ''
|
192
186
|
File.file?(pid_file) && Daemons::Pid.running?(File.read(pid_file).to_i)
|
193
187
|
end
|
188
|
+
|
189
|
+
def wait_for_process_termination(pid)
|
190
|
+
print 'Waiting for background docker-sync to terminate'
|
191
|
+
Timeout::timeout(30) do
|
192
|
+
loop do
|
193
|
+
if process_dead?(pid)
|
194
|
+
puts
|
195
|
+
say_status 'shutdown', 'Background docker-sync has been stopped'
|
196
|
+
return
|
197
|
+
else
|
198
|
+
sleep 1
|
199
|
+
print '.'
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
rescue Timeout::Error
|
204
|
+
puts
|
205
|
+
say_status 'error', 'Background docker-sync daemon failed to stop within 30 seconds', :red
|
206
|
+
exit 70 # EX_SOFTWARE (according to `man sysexits`)
|
207
|
+
end
|
208
|
+
|
209
|
+
def process_dead?(pid)
|
210
|
+
!system("ps -p #{pid} > /dev/null")
|
211
|
+
end
|
194
212
|
end
|
195
213
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docker-sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eugen Mayer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -124,6 +124,20 @@ dependencies:
|
|
124
124
|
- - ">="
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: 1.2.3
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: os
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
127
141
|
description: Sync your code live to docker-containers without losing any performance
|
128
142
|
on OSX
|
129
143
|
email: eugen.mayer@kontextwork.de
|
@@ -139,11 +153,16 @@ files:
|
|
139
153
|
- bin/docker-sync
|
140
154
|
- bin/docker-sync-daemon
|
141
155
|
- bin/docker-sync-stack
|
156
|
+
- lib/docker-sync.rb
|
142
157
|
- lib/docker-sync/compose.rb
|
143
|
-
- lib/docker-sync/config.rb
|
144
|
-
- lib/docker-sync/
|
158
|
+
- lib/docker-sync/config/config_locator.rb
|
159
|
+
- lib/docker-sync/config/config_serializer.rb
|
160
|
+
- lib/docker-sync/config/global_config.rb
|
161
|
+
- lib/docker-sync/config/project_config.rb
|
145
162
|
- lib/docker-sync/execution.rb
|
146
|
-
- lib/docker-sync/preconditions.rb
|
163
|
+
- lib/docker-sync/preconditions/preconditions_linux.rb
|
164
|
+
- lib/docker-sync/preconditions/preconditions_osx.rb
|
165
|
+
- lib/docker-sync/preconditions/strategy.rb
|
147
166
|
- lib/docker-sync/sync_manager.rb
|
148
167
|
- lib/docker-sync/sync_process.rb
|
149
168
|
- lib/docker-sync/sync_strategy/rsync.rb
|
data/lib/docker-sync/config.rb
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
require 'pp'
|
2
|
-
require 'pathname'
|
3
|
-
require 'yaml'
|
4
|
-
require 'dotenv'
|
5
|
-
require 'docker-sync/config_template'
|
6
|
-
|
7
|
-
# this has basically completely reused from Thor::runner.rb - thank you!
|
8
|
-
module DockerSyncConfig
|
9
|
-
|
10
|
-
def initialize(options)
|
11
|
-
load_dotenv
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.load_dotenv
|
15
|
-
env_file = ENV.fetch('DOCKER_SYNC_ENV_FILE', '.env')
|
16
|
-
Dotenv.load(env_file)
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.global_config_location
|
20
|
-
return File.expand_path('~/.docker-sync-global.yml')
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.is_first_run
|
24
|
-
global_config_path = global_config_location
|
25
|
-
return !File.exist?(global_config_path)
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.global_config
|
29
|
-
global_config_path = global_config_location
|
30
|
-
date = DateTime.new(2001, 1, 1) #paste
|
31
|
-
# noinspection RubyStringKeysInHashInspection
|
32
|
-
defaults = {'update_check'=>true, 'update_last_check' => date.iso8601(9), 'update_enforce' => true}
|
33
|
-
if File.exist?(global_config_path)
|
34
|
-
config = ConfigTemplate::interpolate_config_file(global_config_path)
|
35
|
-
config = defaults.merge(config)
|
36
|
-
return config
|
37
|
-
else
|
38
|
-
return defaults
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.global_config_save(config)
|
43
|
-
global_config_path = global_config_location
|
44
|
-
File.open(global_config_path, 'w') {|f| f.write config.to_yaml }
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
def self.project_required_config_version
|
49
|
-
return '2'
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.project_ensure_configuration_version_compatibility(config)
|
53
|
-
return false unless config.key?('version')
|
54
|
-
return false if config['version'].to_s != project_required_config_version.to_s
|
55
|
-
return true
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.project_config_path
|
59
|
-
files = project_config_find
|
60
|
-
if files.length > 0
|
61
|
-
path = files.pop
|
62
|
-
else
|
63
|
-
raise('No docker-sync.yml configuration found in your path ( traversing up ) Did you define it for your project?')
|
64
|
-
end
|
65
|
-
|
66
|
-
begin
|
67
|
-
config = YAML.load_file(path)
|
68
|
-
raise "Version of docker-sync.yml does not match the reqiured one" unless project_ensure_configuration_version_compatibility(config)
|
69
|
-
rescue Exception => e
|
70
|
-
raise "You docker-sync.yml file does either not include a version: \"#{project_required_config_version}\" setting or your setting (#{config['version']}) does not match the required version (#{project_required_config_version}). (Add this if you migrated from docker-sync 0.1.x)"
|
71
|
-
end
|
72
|
-
return path
|
73
|
-
end
|
74
|
-
|
75
|
-
# this has been ruthlessly stolen from Thor/runner.rb - please do not hunt me for that :)
|
76
|
-
def self.project_config_find(skip_lookup = false)
|
77
|
-
# Finds docker-sync.yml by traversing from your current directory down to the root
|
78
|
-
# directory of your system. If at any time we find a docker-sync.yml file, we stop.
|
79
|
-
#
|
80
|
-
#
|
81
|
-
# ==== Example
|
82
|
-
#
|
83
|
-
# If we start at /Users/wycats/dev/thor ...
|
84
|
-
#
|
85
|
-
# 1. /Users/wycats/dev/thor
|
86
|
-
# 2. /Users/wycats/dev
|
87
|
-
# 3. /Users/wycats <-- we find a docker-sync.yml here, so we stop
|
88
|
-
#
|
89
|
-
# Suppose we start at c:\Documents and Settings\james\dev\docker-sync ...
|
90
|
-
#
|
91
|
-
# 1. c:\Documents and Settings\james\dev\docker-sync.yml
|
92
|
-
# 2. c:\Documents and Settings\james\dev
|
93
|
-
# 3. c:\Documents and Settings\james
|
94
|
-
# 4. c:\Documents and Settings
|
95
|
-
# 5. c:\ <-- no docker-sync.yml found!
|
96
|
-
#
|
97
|
-
docker_sync_files = []
|
98
|
-
|
99
|
-
unless skip_lookup
|
100
|
-
Pathname.pwd.ascend do |path|
|
101
|
-
docker_sync_files = globs_for_project_config(path).map { |g| Dir[g] }.flatten
|
102
|
-
break unless docker_sync_files.empty?
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
files = []
|
107
|
-
files += docker_sync_files
|
108
|
-
end
|
109
|
-
|
110
|
-
# Where to look for docker-sync.yml files.
|
111
|
-
#
|
112
|
-
def self.globs_for_project_config(path)
|
113
|
-
path = escape_globs(path)
|
114
|
-
["#{path}/docker-sync.yml"]
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.escape_globs(path)
|
118
|
-
path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&')
|
119
|
-
end
|
120
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require "yaml"
|
2
|
-
require 'dotenv'
|
3
|
-
|
4
|
-
module ConfigTemplate
|
5
|
-
def self.interpolate_config_string(config_string)
|
6
|
-
env_hash = {}
|
7
|
-
ENV.each {|k,v| env_hash[k.to_sym] = v }
|
8
|
-
config_string.gsub!('${', '%{')
|
9
|
-
config_string = config_string % env_hash
|
10
|
-
return YAML.load(config_string)
|
11
|
-
end
|
12
|
-
def self.interpolate_config_file(config_path)
|
13
|
-
# assuming the checks that file exist have already been performed
|
14
|
-
config_string = File.read(config_path)
|
15
|
-
self.interpolate_config_string(config_string)
|
16
|
-
end
|
17
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'mkmf'
|
2
|
-
|
3
|
-
module Preconditions
|
4
|
-
def self.check_all_preconditions
|
5
|
-
docker_available
|
6
|
-
docker_running
|
7
|
-
unison_available
|
8
|
-
unox_available
|
9
|
-
macfsevents_available
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.docker_available
|
13
|
-
if (find_executable0 'docker').nil?
|
14
|
-
raise('Could not find docker binary in path. Please install it, e.g. using "brew install docker" or install docker-for-mac')
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.docker_running
|
19
|
-
`docker ps`
|
20
|
-
if $?.exitstatus > 0
|
21
|
-
raise('No docker daemon seems to be running. Did you start your docker-for-mac / docker-machine?')
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.fswatch_available
|
26
|
-
if (find_executable0 'fswatch').nil?
|
27
|
-
raise('No fswatch available. Install it by "brew install fswatch"')
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.docker_sync_available
|
32
|
-
if (find_executable0 'docker-sync').nil?
|
33
|
-
raise('No docker-sync available. Install it by "gem install docker-sync"')
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.rsync_available
|
38
|
-
if (find_executable0 'rsync').nil?
|
39
|
-
raise('Could not find rsync binary in path. Please install it, e.g. using "brew install rsync"')
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.unison_available
|
44
|
-
if (find_executable0 'unison').nil?
|
45
|
-
raise('Could not find unison binary in path. Please install it, e.g. using "brew install unison"')
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.unox_available
|
50
|
-
if (find_executable0 'unison-fsmonitor').nil?
|
51
|
-
cmd1 = 'curl "https://raw.githubusercontent.com/hnsl/unox/master/unox.py" -o "/usr/local/bin/unison-fsmonitor" \
|
52
|
-
&& chmod +x /usr/local/bin/unison-fsmonitor'
|
53
|
-
|
54
|
-
Thor::Shell::Basic.new.say_status 'warning', 'Could not find unison-fsmonitor (for file watching) binary in $PATH. We try to install unox now (for manual instracutions see https://github.com/hnsl/unox.)', :red
|
55
|
-
if Thor::Shell::Basic.new.yes?('Shall I install unison-fsmonitor for you? (y/N)')
|
56
|
-
system cmd1
|
57
|
-
else
|
58
|
-
raise("Please install it, see https://github.com/hnsl/unox, or simply run :\n #{cmd1}")
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.macfsevents_available
|
65
|
-
`python -c 'import fsevents'`
|
66
|
-
unless $?.success?
|
67
|
-
Thor::Shell::Basic.new.say_status 'warning','Could not find macfsevents. Will try to install it using pip', :red
|
68
|
-
if find_executable0('python') == '/usr/bin/python'
|
69
|
-
Thor::Shell::Basic.new.say_status 'ok','You seem to use the system python, we will need sudo below'
|
70
|
-
sudo = true
|
71
|
-
cmd2 = 'sudo easy_install pip && sudo pip install macfsevents'
|
72
|
-
else
|
73
|
-
Thor::Shell::Basic.new.say_status 'ok','You seem to have a custom python, using non-sudo commands'
|
74
|
-
sudo = false
|
75
|
-
cmd2 = 'easy_install pip && pip install macfsevents'
|
76
|
-
end
|
77
|
-
if sudo
|
78
|
-
question = 'I will ask you for you root password to install macfsevent by running (This will ask for sudo, since we use the system python)'
|
79
|
-
else
|
80
|
-
question = 'I will now install macfsevents for you by running'
|
81
|
-
end
|
82
|
-
|
83
|
-
Thor::Shell::Basic.new.say_status 'info', "#{question}: `#{cmd2}\n\n"
|
84
|
-
if Thor::Shell::Basic.new.yes?('Shall i continue? (y/N)')
|
85
|
-
system cmd2
|
86
|
-
if $?.exitstatus > 0
|
87
|
-
raise('Failed to install macfsevents, please file an issue with the output of the error')
|
88
|
-
end
|
89
|
-
`python -c 'import fsevents'`
|
90
|
-
unless $?.success?
|
91
|
-
raise('Somehow could not successfully install macfsevents even though i treed. Please report this issue')
|
92
|
-
end
|
93
|
-
else
|
94
|
-
raise('Please install macfsevents manually, see https://github.com/EugenMayer/docker-sync/wiki/1.-Installation')
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
end
|
100
|
-
end
|