embulk-input-sftp 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/build.gradle +1 -1
- data/classpath/{embulk-input-sftp-0.2.0.jar → embulk-input-sftp-0.2.1.jar} +0 -0
- data/src/main/java/org/embulk/input/sftp/SftpFileInput.java +68 -5
- data/src/main/java/org/embulk/input/sftp/SftpFileInputPlugin.java +6 -2
- data/src/test/java/org/embulk/input/sftp/TestSftpFileInputPlugin.java +18 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2437f248e08389b72d6954dbb9da3dd6db93964a
|
4
|
+
data.tar.gz: cb24da548a14d3b986ebb21b1f114f4d69bf2962
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 240d0bf66262aabc11f90fa0f53c8e83b11253a2cee7cf384d739804d7dfa074ffe3986f703f1d2fed803bc45c69b1d796ec37c736c6d2fd738e153e4710adf6
|
7
|
+
data.tar.gz: 5ae478d9b5d8ce6429c56579b263d84f25214e1f38442e13494e3d6e49216fea3efa9c6eaa7d0754020583eee80d749a8031b2b7912aabab6d8e8c7332014568
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
## 0.2.1 - 2016-09-12
|
2
|
+
* [maintenance] Fix last_path generation failure when password contains special chars [#15](https://github.com/sakama/embulk-input-sftp/pull/15)
|
3
|
+
|
1
4
|
## 0.2.0 - 2016-08-19
|
2
5
|
|
3
6
|
* [new feature] Support incremental option [#11](https://github.com/sakama/embulk-input-sftp/pull/11)
|
data/build.gradle
CHANGED
Binary file
|
@@ -143,19 +143,82 @@ public class SftpFileInput
|
|
143
143
|
}
|
144
144
|
}
|
145
145
|
|
146
|
-
public static String getRelativePath(Optional<String>
|
146
|
+
public static String getRelativePath(PluginTask task, Optional<String> uri)
|
147
147
|
{
|
148
148
|
try {
|
149
|
-
if (
|
150
|
-
return
|
149
|
+
if (!uri.isPresent()) {
|
150
|
+
return null;
|
151
|
+
}
|
152
|
+
else if (task.getPassword().isPresent()) {
|
153
|
+
return getRelativePathFromURIwithPassword(task, uri);
|
151
154
|
}
|
152
155
|
else {
|
153
|
-
return
|
156
|
+
return new URI(uri.get()).getPath();
|
154
157
|
}
|
155
158
|
}
|
156
159
|
catch (URISyntaxException ex) {
|
157
|
-
|
160
|
+
throw new ConfigException("Failed to generate last_path due to URI parse failure that contains invalid file path.", ex);
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
private static String getRelativePathFromURIwithPassword(final PluginTask task, final Optional<String> uri)
|
165
|
+
{
|
166
|
+
try {
|
167
|
+
return retryExecutor()
|
168
|
+
.withRetryLimit(task.getMaxConnectionRetry())
|
169
|
+
.withInitialRetryWait(500)
|
170
|
+
.withMaxRetryWait(30 * 1000)
|
171
|
+
.runInterruptible(new Retryable<String>() {
|
172
|
+
@Override
|
173
|
+
public String call() throws URISyntaxException, IOException
|
174
|
+
{
|
175
|
+
log.info("Creating last_path from URI contains password in FileList.");
|
176
|
+
StandardFileSystemManager manager = initializeStandardFileSystemManager();
|
177
|
+
|
178
|
+
String prefix = new URI("sftp", initializeUserInfo(task), task.getHost(), task.getPort(), null, null, null).toString();
|
179
|
+
prefix = manager.resolveFile(prefix).toString();
|
180
|
+
// To avoid URI parse failure when password contains special characters
|
181
|
+
String newUri = uri.get().replace(prefix, "sftp://user:password@example.com/");
|
182
|
+
|
183
|
+
return new URI(newUri).getPath();
|
184
|
+
}
|
185
|
+
|
186
|
+
@Override
|
187
|
+
public boolean isRetryableException(Exception exception)
|
188
|
+
{
|
189
|
+
if (exception instanceof URISyntaxException) {
|
190
|
+
// Don't throw cause because URISyntaxException shows password
|
191
|
+
throw new ConfigException("Failed to generate last_path due to URI parse failure that contains invalid file path or password.");
|
192
|
+
}
|
193
|
+
return true;
|
194
|
+
}
|
195
|
+
|
196
|
+
@Override
|
197
|
+
public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait) throws RetryGiveupException
|
198
|
+
{
|
199
|
+
String message = String.format("SFTP List request failed. Retrying %d/%d after %d seconds. Message: %s",
|
200
|
+
retryCount, retryLimit, retryWait / 1000, exception.getMessage());
|
201
|
+
if (retryCount % 3 == 0) {
|
202
|
+
log.warn(message, exception);
|
203
|
+
}
|
204
|
+
else {
|
205
|
+
log.warn(message);
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
@Override
|
210
|
+
public void onGiveup(Exception firstException, Exception lastException) throws RetryGiveupException
|
211
|
+
{
|
212
|
+
}
|
213
|
+
});
|
214
|
+
}
|
215
|
+
catch (RetryGiveupException ex) {
|
216
|
+
throw new ConfigException("Failed to generate last_path due to FTP connection failure");
|
217
|
+
}
|
218
|
+
catch (InterruptedException ex) {
|
219
|
+
Throwables.propagate(ex);
|
158
220
|
}
|
221
|
+
return null;
|
159
222
|
}
|
160
223
|
|
161
224
|
public static FileList listFilesByPrefix(final PluginTask task)
|
@@ -30,11 +30,15 @@ public class SftpFileInputPlugin
|
|
30
30
|
FileInputPlugin.Control control)
|
31
31
|
{
|
32
32
|
PluginTask task = taskSource.loadTask(PluginTask.class);
|
33
|
+
String lastPath = null;
|
34
|
+
if (task.getIncremental()) {
|
35
|
+
lastPath = SftpFileInput.getRelativePath(task, task.getFiles().getLastPath(task.getLastPath()));
|
36
|
+
}
|
33
37
|
control.run(taskSource, taskCount);
|
34
38
|
|
35
39
|
ConfigDiff configDiff = Exec.newConfigDiff();
|
36
|
-
if (task.getIncremental()) {
|
37
|
-
configDiff.set("last_path",
|
40
|
+
if (task.getIncremental() && lastPath != null) {
|
41
|
+
configDiff.set("last_path", lastPath);
|
38
42
|
}
|
39
43
|
|
40
44
|
return configDiff;
|
@@ -227,7 +227,7 @@ public class TestSftpFileInputPlugin
|
|
227
227
|
|
228
228
|
assertEquals(expected.get(0), actual.get(0));
|
229
229
|
assertEquals(expected.get(1), actual.get(1));
|
230
|
-
assertEquals(SftpFileInput.getRelativePath(Optional.of(expected.get(1).get(0))), configDiff.get(String.class, "last_path"));
|
230
|
+
assertEquals(SftpFileInput.getRelativePath(task, Optional.of(expected.get(1).get(0))), configDiff.get(String.class, "last_path"));
|
231
231
|
}
|
232
232
|
|
233
233
|
@Test
|
@@ -373,6 +373,23 @@ public class TestSftpFileInputPlugin
|
|
373
373
|
assertEquals(SftpFileSystemConfigBuilder.PROXY_STREAM, builder.getProxyType(fsOptions));
|
374
374
|
}
|
375
375
|
|
376
|
+
@Test
|
377
|
+
public void testGetRelativePath()
|
378
|
+
{
|
379
|
+
ConfigSource conf = config();
|
380
|
+
String expected = "/path/to/sample.csv";
|
381
|
+
|
382
|
+
conf.set("password", "ABCDE");
|
383
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
384
|
+
String uri = SftpFileInput.getSftpFileUri(task, "/path/to/sample.csv");
|
385
|
+
assertEquals(expected, SftpFileInput.getRelativePath(task, Optional.of(uri)));
|
386
|
+
|
387
|
+
conf.set("password", "ABCD#$¥!%'\"@?<>\\&/_^~|-=+-,{}[]()");
|
388
|
+
task = config.loadConfig(PluginTask.class);
|
389
|
+
uri = SftpFileInput.getSftpFileUri(task, "/path/to/sample.csv");
|
390
|
+
assertEquals(expected, SftpFileInput.getRelativePath(task, Optional.of(uri)));
|
391
|
+
}
|
392
|
+
|
376
393
|
private SshServer createSshServer(String host, int port, final String sshUsername, final String sshPassword)
|
377
394
|
{
|
378
395
|
// setup a mock sftp server
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-sftp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Satoshi Akama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,7 +72,7 @@ files:
|
|
72
72
|
- classpath/commons-io-1.3.2.jar
|
73
73
|
- classpath/commons-logging-1.2.jar
|
74
74
|
- classpath/commons-vfs2-2.1.jar
|
75
|
-
- classpath/embulk-input-sftp-0.2.
|
75
|
+
- classpath/embulk-input-sftp-0.2.1.jar
|
76
76
|
- classpath/jsch-0.1.53.jar
|
77
77
|
homepage: https://github.com/embulk/embulk-input-sftp
|
78
78
|
licenses:
|