docker-sync 0.0.13 → 0.0.14

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