docker-sync 0.0.13 → 0.0.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53b015ea9a91c28a2a853b611f3f0ffc69897cf3
4
- data.tar.gz: 932bbd68a8ea5543626dd4be5e70bdc541efd4c9
3
+ metadata.gz: 5a467b9dee71d933110ea66148ac480c7ed3d9b0
4
+ data.tar.gz: 1533c522f6aa5db93e15d85e4b8a53f61f350e2a
5
5
  SHA512:
6
- metadata.gz: abdd92bb2321085d92b156968a9dd2ece9a65a1dfb655baf2a427308b21cda65a67326d15c2b7a805dfd3e351f378825427c0036706866750458eb305b1fb13b
7
- data.tar.gz: a8ea319b00c764d183baffe56de3ab2ada13b02df3291d304dd7c0ee1d59415d239e1a4af71d3ff2e351963b4bda44fb53f702b3fd5a9c73fa0fa92873a1fcd4
6
+ metadata.gz: 3dfb30f05807f691089c1e106934a29e2bfa54794994b6d7180789824052e1f18532e239058b91f1989b8779c27bbfe58a2adf7db6eaa7c06c1ebc72b2b41004
7
+ data.tar.gz: c09c3b2a2e6615302bf5593e6f5472fa7f364a96e3183a421c09d911042fd20bad5ae0a2e83005f821b0e2883eebd15d4307aa178564b28f1256119b94785c5a
data/Thorfile CHANGED
@@ -1,6 +1,7 @@
1
- #lib = File.expand_path('./lib', __dir__)
2
- $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
3
- thor = File.expand_path('../tasks', __FILE__)
1
+ file = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
2
+ file = File.expand_path(File.dirname(file))
3
+ $LOAD_PATH.unshift File.expand_path('./lib', file)
4
+ thor = File.expand_path('./tasks', file)
4
5
 
5
6
  Dir.glob(File.join(thor, '/**/*.thor')).each { |taskfile|
6
7
  load taskfile
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.13
1
+ 0.0.14
data/bin/docker-sync CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  file = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
3
- $LOAD_PATH.unshift File.expand_path('../../lib', file)
3
+ file = File.expand_path(File.dirname(file))
4
+ $LOAD_PATH.unshift File.expand_path('../lib', file)
4
5
 
5
6
  require 'thor'
6
7
  require 'docker-sync/update_check'
7
8
 
8
- thor = File.expand_path('../../tasks/sync', file)
9
+ thor = File.expand_path('../tasks/sync', file)
9
10
  Dir.glob(File.join(thor, '/**/*.thor')).each { |taskfile|
10
11
  load taskfile
11
12
  }
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  file = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
3
- $LOAD_PATH.unshift File.expand_path('../../lib', file)
3
+ file = File.expand_path(File.dirname(file))
4
+ $LOAD_PATH.unshift File.expand_path('../lib', file)
4
5
 
5
6
 
6
7
  require 'thor'
@@ -16,7 +17,7 @@ require 'docker-sync/update_check'
16
17
  # exit 0
17
18
  #end
18
19
 
19
- thor = File.expand_path('../../tasks/stack', file)
20
+ thor = File.expand_path('../tasks/stack', file)
20
21
  Dir.glob(File.join(thor, '/**/*.thor')).each { |taskfile|
21
22
  # noinspection RubyResolve
22
23
  load taskfile
@@ -45,7 +45,7 @@ module Docker_Rsync
45
45
  @config_syncs.each do |name, config|
46
46
  @config_syncs[name]['config_path'] = @config_path
47
47
  # expand the sync source to remove ~ and similar expressions in the path
48
- @config_syncs[name]['src'] = File.expand_path(@config_syncs[name]['src'])
48
+ @config_syncs[name]['src'] = File.expand_path(@config_syncs[name]['src'], File.dirname(@config_path))
49
49
 
50
50
  # set the global verbose setting, if the sync-endpoint does not define a own one
51
51
  unless config.key?('verbose')
@@ -150,5 +150,17 @@ module Docker_Rsync
150
150
  end
151
151
  }
152
152
  end
153
+
154
+ def watch_stop
155
+ @sync_processes.each { |sync_process|
156
+ sync_process.watch_thread.kill unless sync_process.watch_thread.nil?
157
+ }
158
+ end
159
+
160
+ def watch_start
161
+ @sync_processes.each { |sync_process|
162
+ sync_process.watch
163
+ }
164
+ end
153
165
  end
154
166
  end
@@ -2,6 +2,7 @@ require 'thor/shell'
2
2
  # noinspection RubyResolve
3
3
  require 'docker-sync/sync_strategy/rsync'
4
4
  require 'docker-sync/sync_strategy/unison'
5
+ require 'docker-sync/sync_strategy/unison-dualside'
5
6
  # noinspection RubyResolve
6
7
  require 'docker-sync/watch_strategy/fswatch'
7
8
  require 'docker-sync/watch_strategy/dummy'
@@ -36,6 +37,8 @@ module Docker_Sync
36
37
  @sync_strategy = Docker_Sync::SyncStrategy::Rsync.new(@sync_name, @options)
37
38
  when 'unison'
38
39
  @sync_strategy = Docker_Sync::SyncStrategy::Unison.new(@sync_name, @options)
40
+ when 'unison-dualside'
41
+ @sync_strategy = Docker_Sync::SyncStrategy::Unison_DualSide.new(@sync_name, @options)
39
42
  else
40
43
  @sync_strategy = Docker_Sync::SyncStrategy::Rsync.new(@sync_name, @options)
41
44
  end
@@ -49,9 +52,7 @@ module Docker_Sync
49
52
  case @options['watch_strategy']
50
53
  when 'fswatch'
51
54
  @watch_strategy = Docker_Sync::WatchStrategy::Fswatch.new(@sync_name, @options)
52
- when 'disable'
53
- @watch_strategy = Docker_Sync::WatchStrategy::Dummy.new(@sync_name, @options)
54
- when 'dummy'
55
+ when 'disable','dummy'
55
56
  @watch_strategy = Docker_Sync::WatchStrategy::Dummy.new(@sync_name, @options)
56
57
  else
57
58
  @watch_strategy = Docker_Sync::WatchStrategy::Fswatch.new(@sync_name, @options)
@@ -0,0 +1,199 @@
1
+ require 'thor/shell'
2
+ require 'docker-sync/preconditions'
3
+ require 'open3'
4
+ require 'socket'
5
+
6
+ module Docker_Sync
7
+ module SyncStrategy
8
+ class Unison_DualSide
9
+ include Thor::Shell
10
+
11
+ @options
12
+ @sync_name
13
+ @watch_thread
14
+ @local_server_pid
15
+ UNISON_CONTAINER_PORT = '5000'
16
+ def initialize(sync_name, options)
17
+ @sync_name = sync_name
18
+ @options = options
19
+ # if a custom image is set, apply it
20
+ if @options.key?('image')
21
+ @docker_image = @options['image']
22
+ else
23
+ @docker_image = 'eugenmayer/unison:dualside'
24
+ end
25
+ begin
26
+ Preconditions::unison_available
27
+ rescue Exception => e
28
+ say_status 'error', "#{@sync_name} has been configured to sync with unison, but no unison available", :red
29
+ say_status 'error', e.message, :red
30
+ exit 1
31
+ end
32
+ end
33
+
34
+ def run
35
+ start_container
36
+ start_local_server
37
+ sync
38
+ end
39
+
40
+ def sync
41
+ args = sync_options
42
+ cmd = 'unison ' + args.join(' ')
43
+
44
+ say_status 'command', cmd, :white if @options['verbose']
45
+
46
+ stdout, stderr, exit_status = Open3.capture3(cmd)
47
+ if not exit_status.success?
48
+ say_status 'error', "Error starting sync, exit code #{$?.exitstatus}", :red
49
+ say_status 'message', stderr
50
+ else
51
+ say_status 'ok', "Synced #{@options['src']}", :white
52
+ if @options['verbose']
53
+ say_status 'output', stdout
54
+ end
55
+ end
56
+ end
57
+
58
+ def sync_options
59
+ args = []
60
+
61
+ unless @options['sync_excludes'].nil?
62
+ args = @options['sync_excludes'].map { |pattern| "-ignore='Path #{pattern}'" } + args
63
+ end
64
+ args.push(@options['src'])
65
+ args.push('-auto')
66
+ args.push('-batch')
67
+ args.push('-owner') if @options['sync_userid'] == 'from_host'
68
+ args.push('-numericids') if @options['sync_userid'] == 'from_host'
69
+ args.push(@options['sync_args']) if @options.key?('sync_args')
70
+ args.push("socket://#{@options['sync_host_ip']}:#{@options['sync_host_port']}/")
71
+ args.push('-debug all') if @options['verbose']
72
+ if @options.key?('sync_user') || @options.key?('sync_group') || @options.key?('sync_groupid')
73
+ raise('Unison does not support sync_user, sync_group, sync_groupid - please use rsync if you need that')
74
+ end
75
+ if @options.key?('sync_userid') && @options['sync_userid'] != 'from_host'
76
+ raise('Unison does not support sync_userid with a parameter different than \'from_host\'')
77
+ end
78
+ return args
79
+ end
80
+
81
+ def start_container
82
+ say_status 'ok', 'Starting unison', :white
83
+ container_name = get_container_name
84
+ volume_name = get_volume_name
85
+ env = {}
86
+
87
+ env['ENABLE_WATCH'] = 'true'
88
+ # Excludes for fswatch and unison uses the same value both in the host and in the container
89
+ env['FSWATCH_EXCLUDES'] = @options['watch_excludes'].map { |pattern| "--exclude='#{pattern}'" }.join(' ') if @options.key?('watch_excludes')
90
+ env['UNISON_EXCLUDES'] = @options['sync_excludes'].map { |pattern| "-ignore='Path #{pattern}'" }.join(' ') if @options.key?('sync_excludes')
91
+ # Specify the IP of the host to call the host unison server from the container
92
+ env['HOST_IP'] = get_host_ip
93
+ env['UNISON_HOST_PORT'] = @options['unison-dualside_host_server_port']
94
+
95
+ if @options['sync_userid'] == 'from_host'
96
+ env['UNISON_DIR_OWNER'] = Process.uid
97
+ end
98
+
99
+ additional_docker_env = env.map{ |key,value| "-e #{key}=\"#{value}\"" }.join(' ')
100
+ running = `docker ps --filter 'status=running' --filter 'name=#{container_name}' | grep #{container_name}`
101
+ if running == ''
102
+ say_status 'ok', "#{container_name} container not running", :white if @options['verbose']
103
+ exists = `docker ps --filter "status=exited" --filter "name=#{container_name}" | grep #{container_name}`
104
+ if exists == ''
105
+ say_status 'ok', "creating #{container_name} container", :white if @options['verbose']
106
+ cmd = "docker run -p '#{@options['sync_host_port']}:#{UNISON_CONTAINER_PORT}' \
107
+ -v #{volume_name}:#{@options['dest']} \
108
+ -e UNISON_DIR=#{@options['dest']} \
109
+ #{additional_docker_env} \
110
+ --name #{container_name} \
111
+ -d #{@docker_image}"
112
+ else
113
+ say_status 'ok', "starting #{container_name} container", :white if @options['verbose']
114
+ cmd = "docker start #{container_name}"
115
+ end
116
+ say_status 'command', cmd, :white if @options['verbose']
117
+ `#{cmd}` || raise('Start failed')
118
+ else
119
+ say_status 'ok', "#{container_name} container still running", :blue
120
+ end
121
+ say_status 'ok', "starting initial #{container_name} of src", :white if @options['verbose']
122
+ # this sleep is needed since the container could be not started
123
+ sleep 5 # TODO: replace with unison -testserver
124
+ sync
125
+ say_status 'success', 'Unison server started', :green
126
+ end
127
+
128
+ # Start an unison server on the host
129
+ def start_local_server
130
+ say_status 'ok', 'Starting local unison server', :white
131
+
132
+ if not @options.key?('unison-dualside_host_server_port')
133
+ raise('Missing unison-dualside_host_server_port option. In order to get files synced back automatically from the
134
+ container, you must specify the port of the local unison server.')
135
+ end
136
+ cmd = "unison -socket #{@options['unison-dualside_host_server_port']}"
137
+ say_status 'command', cmd, :white if @options['verbose']
138
+
139
+ # Store the pid of the local unison server, to kill it when docker-sync stops
140
+ @local_server_pid = Process.fork do
141
+ # Run the local unison server in the source folder
142
+ Dir.chdir(@options['src']){
143
+ `#{cmd}` || raise('Start of local unison server failed')
144
+ }
145
+ end
146
+ end
147
+
148
+ # Try to guess the IP of the host to call the unison server from the container
149
+ # Or use the value specified in the config option
150
+ def get_host_ip
151
+ if @options['unison-dualside_host_ip'] != 'auto' && @options.key?('unison-dualside_host_ip')
152
+ host_ip = @options['host_ip']
153
+ elsif @options['unison-dualside_host_ip'] == 'auto' || (not @options.key?('unison-dualside_host_ip'))
154
+ host_ip = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
155
+ end
156
+ return host_ip
157
+ end
158
+
159
+ # Kill the local unison server
160
+ def stop_local_server
161
+ Process.kill "TERM", @local_server_pid
162
+ Process.wait @local_server_pid
163
+ end
164
+
165
+ def get_container_name
166
+ return "#{@sync_name}"
167
+ end
168
+
169
+ def get_volume_name
170
+ return @sync_name
171
+ end
172
+
173
+ def stop_container
174
+ `docker stop #{get_container_name}`
175
+ end
176
+
177
+ def reset_container
178
+ stop_container
179
+ `docker rm #{get_container_name}`
180
+ `docker volume rm #{get_volume_name}`
181
+ end
182
+
183
+ def clean
184
+ reset_container
185
+ end
186
+
187
+ def stop
188
+ say_status 'ok', "Stopping sync container #{get_container_name}"
189
+ begin
190
+ stop_container
191
+ stop_local_server
192
+ rescue Exception => e
193
+ say_status 'error', "Stopping failed of #{get_container_name}:", :red
194
+ puts e.message
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
@@ -63,7 +63,7 @@ module Docker_Sync
63
63
  args.push('-batch')
64
64
  args.push(@options['sync_args']) if @options.key?('sync_args')
65
65
  args.push("socket://#{@options['sync_host_ip']}:#{@options['sync_host_port']}/")
66
- args.push('-debug verbose') if @options['verbose']
66
+ args.push('-debug all') if @options['verbose']
67
67
  if @options.key?('sync_user') || @options.key?('sync_group') || @options.key?('sync_groupid') || @options.key?('sync_userid')
68
68
  raise('Unison does not support sync_user, sync_group, sync_groupid or sync_userid - please use rsync if you need that')
69
69
  end
@@ -1,6 +1,7 @@
1
1
  require 'thor/shell'
2
2
  require 'docker-sync/execution'
3
3
  require 'docker-sync/preconditions'
4
+ require 'pathname'
4
5
 
5
6
  module Docker_Sync
6
7
  module WatchStrategy
@@ -15,6 +16,7 @@ module Docker_Sync
15
16
  def initialize(sync_name, options)
16
17
  @sync_name = sync_name
17
18
  @options = options
19
+ @events_to_watch = %w(AttributeModified Created Link MovedFrom MovedTo Renamed Removed Updated)
18
20
 
19
21
  begin
20
22
  Preconditions::fswatch_available
@@ -50,17 +52,16 @@ module Docker_Sync
50
52
  args = @options['watch_excludes'].map { |pattern| "--exclude='#{pattern}'" } + args
51
53
  end
52
54
  args.push('-orIE')
55
+ args.push(@events_to_watch.map { |pattern| "--event #{pattern}" })
53
56
  args.push(@options['watch_args']) if @options.key?('watch_args')
54
57
  args.push(@options['src'])
55
58
 
56
59
  sync_command = 'thor sync:sync'
57
- begin
58
- Preconditions::docker_sync_available
60
+ exec_name =File.basename($PROGRAM_NAME)
61
+ if exec_name != 'thor'
59
62
  sync_command = 'docker-sync sync'
60
- rescue Exception => e
61
- say_status 'warning', 'docker-sync not available, assuming dev mode, using thor', :yellow
62
- puts e.message
63
- sync_command = 'thor sync:sync'
63
+ else
64
+ say_status 'warning', 'Called user thor, not docker-sync* wise, assuming dev mode, using thor', :yellow
64
65
  end
65
66
  args.push(" | xargs -I -n1 #{sync_command} -n #{@sync_name} --config='#{@options['config_path']}'")
66
67
  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.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eugen Mayer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-13 00:00:00.000000000 Z
11
+ date: 2016-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -84,6 +84,7 @@ files:
84
84
  - lib/docker-sync/sync_manager.rb
85
85
  - lib/docker-sync/sync_process.rb
86
86
  - lib/docker-sync/sync_strategy/rsync.rb
87
+ - lib/docker-sync/sync_strategy/unison-dualside.rb
87
88
  - lib/docker-sync/sync_strategy/unison.rb
88
89
  - lib/docker-sync/update_check.rb
89
90
  - lib/docker-sync/watch_strategy/dummy.rb