embulk-output-sftp 0.0.4 → 0.0.5

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: 40a3cc8b06b682fe155dc167c0e0fd997a18b4a5
4
- data.tar.gz: 1a0ef68bdb08197ce77cb6e4e897fb05121b142a
3
+ metadata.gz: 865291280d7c6936d0e4f12655a00b854f880153
4
+ data.tar.gz: dfe086b9210d16e7da2e21d5f77e42c38bd7f23b
5
5
  SHA512:
6
- metadata.gz: 378b46609dffc450f10602326e88676f75f29f05b3436dffebaa6722004cff6799a361beb39de318ffaf076908ee00719cdadcedbb29eee1fac97a1a2b33111b
7
- data.tar.gz: 2f383b02a595884182b58ebb36ce3c5b4e804d00ce1f6575cd67099094c5c85f48ec33c2b50bdc070c1d6e80d8e7ce29bc4736b71e45ee43107f94b84cc8f0c8
6
+ metadata.gz: b226b3a68c6e81ddf17ff22577ffd80cae2b58201b18a38bae681b0729e531769426e3f760694d36121e1885a6dfc21383a91c4fe5664203aafb58ad8c00c0fd
7
+ data.tar.gz: 6bdda04f1ba31689656896323098be6e43e34c88cec3ea7922c6e0c55c6d8bc3b593f89ea863fcefb8a537da2ae38e6a2ebf159008e44e5d475cc025014fe80d
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ 0.0.5 (2016-03-09)
2
+ ==================
3
+ - Add: Support MapReduce executor
4
+ - https://github.com/civitaspo/embulk-output-sftp/pull/8
5
+ - Fix: Use ConfigException instead of RuntimeException
6
+ - https://github.com/civitaspo/embulk-output-sftp/pull/9/files
7
+ - Fix: Check to exist parent directory before uploading files
8
+ - https://github.com/civitaspo/embulk-output-sftp/pull/13
9
+ - Add: Support proxy settings
10
+ - https://github.com/civitaspo/embulk-output-sftp/pull/11
data/README.md CHANGED
@@ -14,10 +14,10 @@ Stores files on a SFTP Server
14
14
  ## Configuration
15
15
 
16
16
  - **host**: (string, required)
17
- - **port**: (string, default: `22`)
17
+ - **port**: (int, default: `22`)
18
18
  - **user**: (string, required)
19
19
  - **password**: (string, default: `null`)
20
- - **secret_key_file**: (string, default: `null`)
20
+ - **secret_key_file**: (string, default: `null`) [see below](#secret-keyfile-configuration)
21
21
  - **secret_key_passphrase**: (string, default: `""`)
22
22
  - **user_directory_is_root**: (boolean, default: `true`)
23
23
  - **timeout**: sftp connection timeout seconds (integer, default: `600`)
@@ -25,6 +25,19 @@ Stores files on a SFTP Server
25
25
  - **file_ext**: Extension of output files (string, required)
26
26
  - **sequence_format**: Format for sequence part of output files (string, default: `".%03d.%02d"`)
27
27
 
28
+ ### Proxy configuration
29
+
30
+ - **proxy**:
31
+ - **type**: (string(http | socks | stream), required, default: `null`)
32
+ - **http**: use HTTP Proxy
33
+ - **socks**: use SOCKS Proxy
34
+ - **stream**: Connects to the SFTP server through a remote host reached by SSH
35
+ - **host**: (string, required)
36
+ - **port**: (int, default: `22`)
37
+ - **user**: (string, optional)
38
+ - **password**: (string, optional, default: `null`)
39
+ - **command**: (string, optional)
40
+
28
41
  ## Example
29
42
 
30
43
  ```yaml
@@ -42,6 +55,53 @@ out:
42
55
  sequence_format: ".%01d%01d"
43
56
  ```
44
57
 
58
+ With proxy
59
+ ```yaml
60
+ out:
61
+ type: sftp
62
+ host: 127.0.0.1
63
+ port: 22
64
+ user: embulk
65
+ secret_key_file: /Users/embulk/.ssh/id_rsa
66
+ secret_key_passphrase: secret_pass
67
+ user_directory_is_root: false
68
+ timeout: 600
69
+ path_prefix: /data/sftp
70
+ proxy:
71
+ type: http
72
+ host: proxy_host
73
+ port: 8080
74
+ user: proxy_user
75
+ password: proxy_secret_pass
76
+ command:
77
+ ```
78
+
79
+ ### Secret Keyfile configuration
80
+
81
+ Please set path of secret_key_file as follows.
82
+ ```yaml
83
+ out:
84
+ type: sftp
85
+ ...
86
+ secret_key_file: /path/to/id_rsa
87
+ ...
88
+ ```
89
+
90
+ You can also embed contents of secret_key_file at config.yml.
91
+ ```yaml
92
+ out:
93
+ type: sftp
94
+ ...
95
+ secret_key_file:
96
+ content |
97
+ -----BEGIN RSA PRIVATE KEY-----
98
+ ABCDEFG...
99
+ HIJKLMN...
100
+ OPQRSTU...
101
+ -----END RSA PRIVATE KEY-----
102
+ ...
103
+ ```
104
+
45
105
  ## Run Example
46
106
  replace settings in `example/sample.yml` before running.
47
107
 
@@ -59,3 +119,7 @@ $ ./gradlew gem # -t to watch change of files and rebuild continuously
59
119
  ## Note
60
120
 
61
121
  This plugin uses "org.apache.commons:commons-vfs" and the library uses the logger "org.apache.commons.logging.Log". So, this plugin suppress the logger's message except when embulk log level is debug.
122
+
123
+ ## Contributors
124
+ - Satoshi Akama (@sakama)
125
+ - Rudolph Miller (@Rudolph-Miller)
data/build.gradle CHANGED
@@ -4,6 +4,7 @@ plugins {
4
4
  id "com.github.kt3k.coveralls" version "2.4.0"
5
5
  id "jacoco"
6
6
  id "java"
7
+ id "checkstyle"
7
8
  }
8
9
  import com.github.jrubygradle.JRubyExec
9
10
  repositories {
@@ -14,20 +15,22 @@ configurations {
14
15
  provided
15
16
  }
16
17
 
17
- version = "0.0.4"
18
+ version = "0.0.5"
18
19
  sourceCompatibility = 1.7
19
20
  targetCompatibility = 1.7
20
21
 
21
22
  dependencies {
22
- compile "org.embulk:embulk-core:0.7.+"
23
- provided "org.embulk:embulk-core:0.7.+"
23
+ compile "org.embulk:embulk-core:0.8.6"
24
+ provided "org.embulk:embulk-core:0.8.6"
24
25
  // compile "YOUR_JAR_DEPENDENCY_GROUP:YOUR_JAR_DEPENDENCY_MODULE:YOUR_JAR_DEPENDENCY_VERSION"
25
26
  compile "org.apache.commons:commons-vfs2:2.+"
26
27
  compile "com.jcraft:jsch:0.1.53"
27
28
  testCompile "junit:junit:4.+"
28
- testCompile "org.embulk:embulk-core:0.7.+:tests"
29
- testCompile "org.embulk:embulk-standards:0.7.+"
30
- testCompile "org.apache.sshd:apache-sshd:1.+"
29
+ testCompile "org.embulk:embulk-core:0.8.6:tests"
30
+ testCompile "org.embulk:embulk-standards:0.8.6"
31
+ testCompile "org.apache.sshd:apache-sshd:1.1.0+"
32
+ testCompile "org.littleshoot:littleproxy:1.1.0-beta1"
33
+ testCompile "io.netty:netty-all:4.0.34.Final"
31
34
  }
32
35
 
33
36
  jacocoTestReport {
@@ -44,6 +47,23 @@ task classpath(type: Copy, dependsOn: ["jar"]) {
44
47
  }
45
48
  clean { delete "classpath" }
46
49
 
50
+ checkstyle {
51
+ configFile = file("${project.rootDir}/config/checkstyle/checkstyle.xml")
52
+ toolVersion = '6.14.1'
53
+ }
54
+ checkstyleMain {
55
+ configFile = file("${project.rootDir}/config/checkstyle/default.xml")
56
+ ignoreFailures = true
57
+ }
58
+ checkstyleTest {
59
+ configFile = file("${project.rootDir}/config/checkstyle/default.xml")
60
+ ignoreFailures = true
61
+ }
62
+ task checkstyle(type: Checkstyle) {
63
+ classpath = sourceSets.main.output + sourceSets.test.output
64
+ source = sourceSets.main.allJava + sourceSets.test.allJava
65
+ }
66
+
47
67
  task gem(type: JRubyExec, dependsOn: ["gemspec", "classpath"]) {
48
68
  jrubyArgs "-rrubygems/gem_runner", "-eGem::GemRunner.new.run(ARGV)", "build"
49
69
  script "${project.name}.gemspec"
@@ -0,0 +1,128 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE module PUBLIC
3
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
4
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
5
+ <module name="Checker">
6
+ <!-- https://github.com/facebook/presto/blob/master/src/checkstyle/checks.xml -->
7
+ <module name="FileTabCharacter"/>
8
+ <module name="NewlineAtEndOfFile">
9
+ <property name="lineSeparator" value="lf"/>
10
+ </module>
11
+ <module name="RegexpMultiline">
12
+ <property name="format" value="\r"/>
13
+ <property name="message" value="Line contains carriage return"/>
14
+ </module>
15
+ <module name="RegexpMultiline">
16
+ <property name="format" value=" \n"/>
17
+ <property name="message" value="Line has trailing whitespace"/>
18
+ </module>
19
+ <module name="RegexpMultiline">
20
+ <property name="format" value="\{\n\n"/>
21
+ <property name="message" value="Blank line after opening brace"/>
22
+ </module>
23
+ <module name="RegexpMultiline">
24
+ <property name="format" value="\n\n\s*\}"/>
25
+ <property name="message" value="Blank line before closing brace"/>
26
+ </module>
27
+ <module name="RegexpMultiline">
28
+ <property name="format" value="\n\n\n"/>
29
+ <property name="message" value="Multiple consecutive blank lines"/>
30
+ </module>
31
+ <module name="RegexpMultiline">
32
+ <property name="format" value="\n\n\Z"/>
33
+ <property name="message" value="Blank line before end of file"/>
34
+ </module>
35
+ <module name="RegexpMultiline">
36
+ <property name="format" value="Preconditions\.checkNotNull"/>
37
+ <property name="message" value="Use of checkNotNull"/>
38
+ </module>
39
+
40
+ <module name="TreeWalker">
41
+ <module name="EmptyBlock">
42
+ <property name="option" value="text"/>
43
+ <property name="tokens" value="
44
+ LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF,
45
+ LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, INSTANCE_INIT, STATIC_INIT"/>
46
+ </module>
47
+ <module name="EmptyStatement"/>
48
+ <module name="EmptyForInitializerPad"/>
49
+ <module name="EmptyForIteratorPad">
50
+ <property name="option" value="space"/>
51
+ </module>
52
+ <module name="MethodParamPad">
53
+ <property name="allowLineBreaks" value="true"/>
54
+ <property name="option" value="nospace"/>
55
+ </module>
56
+ <module name="ParenPad"/>
57
+ <module name="TypecastParenPad"/>
58
+ <module name="NeedBraces"/>
59
+ <module name="LeftCurly">
60
+ <property name="option" value="nl"/>
61
+ <property name="tokens" value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, METHOD_DEF"/>
62
+ </module>
63
+ <module name="LeftCurly">
64
+ <property name="option" value="eol"/>
65
+ <property name="tokens" value="
66
+ LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR,
67
+ LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE"/>
68
+ </module>
69
+ <module name="RightCurly">
70
+ <property name="option" value="alone"/>
71
+ </module>
72
+ <module name="GenericWhitespace"/>
73
+ <module name="WhitespaceAfter"/>
74
+ <module name="NoWhitespaceBefore"/>
75
+
76
+ <module name="UpperEll"/>
77
+ <module name="DefaultComesLast"/>
78
+ <module name="ArrayTypeStyle"/>
79
+ <module name="MultipleVariableDeclarations"/>
80
+ <module name="ModifierOrder"/>
81
+ <module name="OneStatementPerLine"/>
82
+ <module name="StringLiteralEquality"/>
83
+ <module name="MutableException"/>
84
+ <module name="EqualsHashCode"/>
85
+ <module name="InnerAssignment"/>
86
+ <module name="InterfaceIsType"/>
87
+ <module name="HideUtilityClassConstructor"/>
88
+
89
+ <module name="MemberName"/>
90
+ <module name="LocalVariableName"/>
91
+ <module name="LocalFinalVariableName"/>
92
+ <module name="TypeName"/>
93
+ <module name="PackageName"/>
94
+ <module name="ParameterName"/>
95
+ <module name="StaticVariableName"/>
96
+ <module name="ClassTypeParameterName">
97
+ <property name="format" value="^[A-Z][0-9]?$"/>
98
+ </module>
99
+ <module name="MethodTypeParameterName">
100
+ <property name="format" value="^[A-Z][0-9]?$"/>
101
+ </module>
102
+
103
+ <module name="AvoidStarImport"/>
104
+ <module name="RedundantImport"/>
105
+ <module name="UnusedImports"/>
106
+ <module name="ImportOrder">
107
+ <property name="groups" value="*,javax,java"/>
108
+ <property name="separated" value="true"/>
109
+ <property name="option" value="bottom"/>
110
+ <property name="sortStaticImportsAlphabetically" value="true"/>
111
+ </module>
112
+
113
+ <module name="WhitespaceAround">
114
+ <property name="allowEmptyConstructors" value="true"/>
115
+ <property name="allowEmptyMethods" value="true"/>
116
+ <property name="ignoreEnhancedForColon" value="false"/>
117
+ <property name="tokens" value="
118
+ ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN,
119
+ BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LE,
120
+ LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
121
+ LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
122
+ LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE,
123
+ LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL,
124
+ PLUS, PLUS_ASSIGN, QUESTION, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN,
125
+ STAR, STAR_ASSIGN, TYPE_EXTENSION_AND"/>
126
+ </module>
127
+ </module>
128
+ </module>
@@ -0,0 +1,108 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE module PUBLIC
3
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
4
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
5
+ <!--
6
+ This is a subset of ./checkstyle.xml which allows some loose styles
7
+ -->
8
+ <module name="Checker">
9
+ <module name="FileTabCharacter"/>
10
+ <module name="NewlineAtEndOfFile">
11
+ <property name="lineSeparator" value="lf"/>
12
+ </module>
13
+ <module name="RegexpMultiline">
14
+ <property name="format" value="\r"/>
15
+ <property name="message" value="Line contains carriage return"/>
16
+ </module>
17
+ <module name="RegexpMultiline">
18
+ <property name="format" value=" \n"/>
19
+ <property name="message" value="Line has trailing whitespace"/>
20
+ </module>
21
+ <module name="RegexpMultiline">
22
+ <property name="format" value="\n\n\n"/>
23
+ <property name="message" value="Multiple consecutive blank lines"/>
24
+ </module>
25
+ <module name="RegexpMultiline">
26
+ <property name="format" value="\n\n\Z"/>
27
+ <property name="message" value="Blank line before end of file"/>
28
+ </module>
29
+
30
+ <module name="TreeWalker">
31
+ <module name="EmptyBlock">
32
+ <property name="option" value="text"/>
33
+ <property name="tokens" value="
34
+ LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF,
35
+ LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, INSTANCE_INIT, STATIC_INIT"/>
36
+ </module>
37
+ <module name="EmptyStatement"/>
38
+ <module name="EmptyForInitializerPad"/>
39
+ <module name="EmptyForIteratorPad">
40
+ <property name="option" value="space"/>
41
+ </module>
42
+ <module name="MethodParamPad">
43
+ <property name="allowLineBreaks" value="true"/>
44
+ <property name="option" value="nospace"/>
45
+ </module>
46
+ <module name="ParenPad"/>
47
+ <module name="TypecastParenPad"/>
48
+ <module name="NeedBraces"/>
49
+ <module name="LeftCurly">
50
+ <property name="option" value="nl"/>
51
+ <property name="tokens" value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, METHOD_DEF"/>
52
+ </module>
53
+ <module name="LeftCurly">
54
+ <property name="option" value="eol"/>
55
+ <property name="tokens" value="
56
+ LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR,
57
+ LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE"/>
58
+ </module>
59
+ <module name="RightCurly">
60
+ <property name="option" value="alone"/>
61
+ </module>
62
+ <module name="GenericWhitespace"/>
63
+ <module name="WhitespaceAfter"/>
64
+ <module name="NoWhitespaceBefore"/>
65
+
66
+ <module name="UpperEll"/>
67
+ <module name="DefaultComesLast"/>
68
+ <module name="ArrayTypeStyle"/>
69
+ <module name="MultipleVariableDeclarations"/>
70
+ <module name="ModifierOrder"/>
71
+ <module name="OneStatementPerLine"/>
72
+ <module name="StringLiteralEquality"/>
73
+ <module name="MutableException"/>
74
+ <module name="EqualsHashCode"/>
75
+ <module name="InnerAssignment"/>
76
+ <module name="InterfaceIsType"/>
77
+ <module name="HideUtilityClassConstructor"/>
78
+
79
+ <module name="MemberName"/>
80
+ <module name="LocalVariableName"/>
81
+ <module name="LocalFinalVariableName"/>
82
+ <module name="TypeName"/>
83
+ <module name="PackageName"/>
84
+ <module name="ParameterName"/>
85
+ <module name="StaticVariableName"/>
86
+ <module name="ClassTypeParameterName">
87
+ <property name="format" value="^[A-Z][0-9]?$"/>
88
+ </module>
89
+ <module name="MethodTypeParameterName">
90
+ <property name="format" value="^[A-Z][0-9]?$"/>
91
+ </module>
92
+
93
+ <module name="WhitespaceAround">
94
+ <property name="allowEmptyConstructors" value="true"/>
95
+ <property name="allowEmptyMethods" value="true"/>
96
+ <property name="ignoreEnhancedForColon" value="false"/>
97
+ <property name="tokens" value="
98
+ ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN,
99
+ BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LE,
100
+ LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
101
+ LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
102
+ LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE,
103
+ LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL,
104
+ PLUS, PLUS_ASSIGN, QUESTION, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN,
105
+ STAR, STAR_ASSIGN, TYPE_EXTENSION_AND"/>
106
+ </module>
107
+ </module>
108
+ </module>
Binary file
@@ -1,6 +1,6 @@
1
- #Tue Aug 11 00:26:20 PDT 2015
1
+ #Wed Jan 13 12:41:02 JST 2016
2
2
  distributionBase=GRADLE_USER_HOME
3
3
  distributionPath=wrapper/dists
4
4
  zipStoreBase=GRADLE_USER_HOME
5
5
  zipStorePath=wrapper/dists
6
- distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
@@ -0,0 +1,85 @@
1
+ package org.embulk.output.sftp;
2
+
3
+ import com.fasterxml.jackson.annotation.JsonCreator;
4
+ import com.fasterxml.jackson.annotation.JsonValue;
5
+ import com.google.common.base.Optional;
6
+ import org.apache.commons.vfs2.FileSystemOptions;
7
+ import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
8
+ import org.embulk.config.Config;
9
+ import org.embulk.config.ConfigDefault;
10
+ import org.embulk.config.ConfigException;
11
+ import org.embulk.config.Task;
12
+
13
+ import java.util.Locale;
14
+
15
+ interface ProxyTask
16
+ extends Task
17
+ {
18
+ @Config("type")
19
+ public ProxyType getType();
20
+
21
+ @Config("host")
22
+ public Optional<String> getHost();
23
+
24
+ @Config("user")
25
+ @ConfigDefault("null")
26
+ public Optional<String> getUser();
27
+
28
+ @Config("password")
29
+ @ConfigDefault("null")
30
+ public Optional<String> getPassword();
31
+
32
+ @Config("port")
33
+ @ConfigDefault("22")
34
+ public int getPort();
35
+
36
+ @Config("command")
37
+ @ConfigDefault("null")
38
+ public Optional<String> getCommand();
39
+
40
+ public enum ProxyType
41
+ {
42
+ HTTP,
43
+ SOCKS,
44
+ STREAM;
45
+
46
+ @JsonValue
47
+ @Override
48
+ public String toString()
49
+ {
50
+ return name().toLowerCase(Locale.ENGLISH);
51
+ }
52
+
53
+ @JsonCreator
54
+ public static ProxyType fromString(String value)
55
+ {
56
+ switch (value) {
57
+ case "http":
58
+ return HTTP;
59
+ case "socks":
60
+ return SOCKS;
61
+ case "stream":
62
+ return STREAM;
63
+ default:
64
+ throw new ConfigException(String.format("Unknown proxy type '%s'. Supported proxy types are http, socks, stream", value));
65
+ }
66
+ }
67
+
68
+ public static SftpFileSystemConfigBuilder setProxyType(SftpFileSystemConfigBuilder builder, FileSystemOptions fsOptions, ProxyTask.ProxyType type)
69
+ {
70
+ SftpFileSystemConfigBuilder.ProxyType setType = null;
71
+ switch (type) {
72
+ case HTTP:
73
+ setType = SftpFileSystemConfigBuilder.PROXY_HTTP;
74
+ break;
75
+ case SOCKS:
76
+ setType = SftpFileSystemConfigBuilder.PROXY_SOCKS5;
77
+ break;
78
+ case STREAM:
79
+ setType = SftpFileSystemConfigBuilder.PROXY_STREAM;
80
+ }
81
+ builder.setProxyType(fsOptions, setType);
82
+ return builder;
83
+ }
84
+ }
85
+ }
@@ -1,5 +1,6 @@
1
1
  package org.embulk.output.sftp;
2
2
 
3
+ import com.google.common.base.Function;
3
4
  import com.google.common.base.Throwables;
4
5
  import org.apache.commons.vfs2.FileObject;
5
6
  import org.apache.commons.vfs2.FileSystemException;
@@ -7,11 +8,13 @@ import org.apache.commons.vfs2.FileSystemOptions;
7
8
  import org.apache.commons.vfs2.impl.StandardFileSystemManager;
8
9
  import org.apache.commons.vfs2.provider.sftp.IdentityInfo;
9
10
  import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
11
+ import org.embulk.config.ConfigException;
10
12
  import org.embulk.config.TaskReport;
11
13
  import org.embulk.spi.Buffer;
12
14
  import org.embulk.spi.Exec;
13
15
  import org.embulk.spi.FileOutput;
14
16
  import org.embulk.spi.TransactionalFileOutput;
17
+ import org.embulk.spi.unit.LocalFile;
15
18
  import org.slf4j.Logger;
16
19
 
17
20
  import java.io.File;
@@ -56,7 +59,7 @@ public class SftpFileOutput
56
59
  }
57
60
  catch (FileSystemException e) {
58
61
  logger.error(e.getMessage());
59
- throw new RuntimeException(e);
62
+ throw new ConfigException(e);
60
63
  }
61
64
 
62
65
  return manager;
@@ -76,18 +79,45 @@ public class SftpFileOutput
76
79
  FileSystemOptions fsOptions = new FileSystemOptions();
77
80
 
78
81
  try {
79
- SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(fsOptions, task.getUserDirIsRoot());
80
- SftpFileSystemConfigBuilder.getInstance().setTimeout(fsOptions, task.getSftpConnectionTimeout());
81
- SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");
82
+ SftpFileSystemConfigBuilder builder = SftpFileSystemConfigBuilder.getInstance();
83
+ builder.setUserDirIsRoot(fsOptions, task.getUserDirIsRoot());
84
+ builder.setTimeout(fsOptions, task.getSftpConnectionTimeout());
85
+ builder.setStrictHostKeyChecking(fsOptions, "no");
82
86
  if (task.getSecretKeyFilePath().isPresent()) {
83
- IdentityInfo identityInfo = new IdentityInfo(new File((task.getSecretKeyFilePath().get())), task.getSecretKeyPassphrase().getBytes());
84
- SftpFileSystemConfigBuilder.getInstance().setIdentityInfo(fsOptions, identityInfo);
87
+ IdentityInfo identityInfo = new IdentityInfo(
88
+ new File((task.getSecretKeyFilePath().transform(localFileToPathString()).get())),
89
+ task.getSecretKeyPassphrase().getBytes()
90
+ );
91
+ builder.setIdentityInfo(fsOptions, identityInfo);
85
92
  logger.info("set identity: {}", task.getSecretKeyFilePath().get());
86
93
  }
94
+
95
+ if (task.getProxy().isPresent()) {
96
+ ProxyTask proxy = task.getProxy().get();
97
+
98
+ ProxyTask.ProxyType.setProxyType(builder, fsOptions, proxy.getType());
99
+
100
+ if (proxy.getHost().isPresent()) {
101
+ builder.setProxyHost(fsOptions, proxy.getHost().get());
102
+ builder.setProxyPort(fsOptions, proxy.getPort());
103
+ }
104
+
105
+ if (proxy.getUser().isPresent()) {
106
+ builder.setProxyUser(fsOptions, proxy.getUser().get());
107
+ }
108
+
109
+ if (proxy.getPassword().isPresent()) {
110
+ builder.setProxyPassword(fsOptions, proxy.getPassword().get());
111
+ }
112
+
113
+ if (proxy.getCommand().isPresent()) {
114
+ builder.setProxyCommand(fsOptions, proxy.getCommand().get());
115
+ }
116
+ }
87
117
  }
88
118
  catch (FileSystemException e) {
89
119
  logger.error(e.getMessage());
90
- throw new RuntimeException(e);
120
+ throw new ConfigException(e);
91
121
  }
92
122
 
93
123
  return fsOptions;
@@ -137,7 +167,9 @@ public class SftpFileOutput
137
167
  logger.error(e.getMessage());
138
168
  Throwables.propagate(e);
139
169
  }
140
- buffer.release();
170
+ finally {
171
+ buffer.release();
172
+ }
141
173
  }
142
174
 
143
175
  @Override
@@ -161,10 +193,9 @@ public class SftpFileOutput
161
193
  @Override
162
194
  public TaskReport commit()
163
195
  {
164
- return null;
196
+ return Exec.newTaskReport();
165
197
  }
166
198
 
167
-
168
199
  private void closeCurrentFile()
169
200
  {
170
201
  if (currentFile == null) {
@@ -194,7 +225,7 @@ public class SftpFileOutput
194
225
  }
195
226
  catch (URISyntaxException e) {
196
227
  logger.error(e.getMessage());
197
- throw new RuntimeException(e);
228
+ throw new ConfigException(e);
198
229
  }
199
230
  }
200
231
 
@@ -209,7 +240,15 @@ public class SftpFileOutput
209
240
  int count = 0;
210
241
  while (true) {
211
242
  try {
212
- return manager.resolveFile(sftpUri.toString(), fsOptions);
243
+ FileObject file = manager.resolveFile(sftpUri.toString(), fsOptions);
244
+ if (file.getParent().exists()) {
245
+ logger.info("parent directory {} exists there", file.getParent());
246
+ return file;
247
+ }
248
+ else {
249
+ logger.info("trying to create parent directory {}", file.getParent());
250
+ file.getParent().createFolder();
251
+ }
213
252
  }
214
253
  catch (FileSystemException e) {
215
254
  if (++count == maxConnectionRetry) {
@@ -230,4 +269,15 @@ public class SftpFileOutput
230
269
  }
231
270
  }
232
271
  }
272
+
273
+ private Function<LocalFile, String> localFileToPathString()
274
+ {
275
+ return new Function<LocalFile, String>()
276
+ {
277
+ public String apply(LocalFile file)
278
+ {
279
+ return file.getPath().toString();
280
+ }
281
+ };
282
+ }
233
283
  }
@@ -11,6 +11,7 @@ import org.embulk.config.TaskSource;
11
11
  import org.embulk.spi.Exec;
12
12
  import org.embulk.spi.FileOutputPlugin;
13
13
  import org.embulk.spi.TransactionalFileOutput;
14
+ import org.embulk.spi.unit.LocalFile;
14
15
  import org.slf4j.Logger;
15
16
 
16
17
  import java.util.List;
@@ -39,7 +40,8 @@ public class SftpFileOutputPlugin
39
40
 
40
41
  @Config("secret_key_file")
41
42
  @ConfigDefault("null")
42
- public Optional<String> getSecretKeyFilePath();
43
+ public Optional<LocalFile> getSecretKeyFilePath();
44
+ public void setSecretKeyFilePath(Optional<LocalFile> secretKeyFilePath);
43
45
 
44
46
  @Config("secret_key_passphrase")
45
47
  @ConfigDefault("\"\"")
@@ -67,6 +69,9 @@ public class SftpFileOutputPlugin
67
69
  @ConfigDefault("\"%03d.%02d.\"")
68
70
  public String getSequenceFormat();
69
71
 
72
+ @Config("proxy")
73
+ @ConfigDefault("null")
74
+ public Optional<ProxyTask> getProxy();
70
75
  }
71
76
 
72
77
  @Override
@@ -2,8 +2,6 @@ package org.embulk.output.sftp;
2
2
 
3
3
  import com.google.common.base.Charsets;
4
4
  import com.google.common.base.Optional;
5
- import com.google.common.base.Splitter;
6
- import com.google.common.base.Throwables;
7
5
  import com.google.common.collect.Lists;
8
6
  import com.google.common.io.Resources;
9
7
  import org.apache.commons.vfs2.FileSystemException;
@@ -13,11 +11,12 @@ import org.apache.sshd.server.Command;
13
11
  import org.apache.sshd.server.SshServer;
14
12
  import org.apache.sshd.server.auth.password.PasswordAuthenticator;
15
13
  import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
16
- import org.apache.sshd.server.command.ScpCommandFactory;
17
14
  import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
15
+ import org.apache.sshd.server.scp.ScpCommandFactory;
18
16
  import org.apache.sshd.server.session.ServerSession;
19
17
  import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
20
18
  import org.embulk.EmbulkTestRuntime;
19
+ import org.embulk.config.ConfigException;
21
20
  import org.embulk.config.ConfigLoader;
22
21
  import org.embulk.config.ConfigSource;
23
22
  import org.embulk.config.TaskReport;
@@ -32,37 +31,39 @@ import org.embulk.spi.Schema;
32
31
  import org.embulk.spi.TransactionalPageOutput;
33
32
  import org.embulk.spi.time.Timestamp;
34
33
  import org.hamcrest.CoreMatchers;
35
- import org.hamcrest.Matcher;
36
34
  import org.junit.After;
37
35
  import org.junit.Before;
38
36
  import org.junit.Rule;
39
37
  import org.junit.Test;
40
38
  import org.junit.rules.ExpectedException;
41
39
  import org.junit.rules.TemporaryFolder;
40
+ import org.littleshoot.proxy.HttpProxyServer;
41
+ import org.littleshoot.proxy.impl.DefaultHttpProxyServer;
42
42
  import org.slf4j.Logger;
43
43
 
44
44
  import java.io.File;
45
45
  import java.io.IOException;
46
46
  import java.nio.file.DirectoryStream;
47
- import java.nio.file.FileSystems;
48
47
  import java.nio.file.Files;
49
48
  import java.nio.file.Path;
50
- import java.nio.file.PathMatcher;
51
49
  import java.nio.file.Paths;
52
50
  import java.security.PublicKey;
53
- import java.util.Arrays;
54
51
  import java.util.Collections;
55
52
  import java.util.List;
56
53
 
57
54
  import static com.google.common.io.Files.readLines;
58
- import static org.embulk.spi.type.Types.*;
55
+ import static org.embulk.spi.type.Types.BOOLEAN;
56
+ import static org.embulk.spi.type.Types.DOUBLE;
57
+ import static org.embulk.spi.type.Types.JSON;
58
+ import static org.embulk.spi.type.Types.LONG;
59
+ import static org.embulk.spi.type.Types.STRING;
60
+ import static org.embulk.spi.type.Types.TIMESTAMP;
59
61
  import static org.hamcrest.CoreMatchers.containsString;
60
62
  import static org.hamcrest.CoreMatchers.hasItem;
61
- import static org.hamcrest.CoreMatchers.instanceOf;
62
- import static org.hamcrest.MatcherAssert.*;
63
- import static org.hamcrest.core.Is.is;
64
63
  import static org.junit.Assert.assertEquals;
65
- //import static org.hamcrest.Matchers.*;
64
+ import static org.junit.Assert.assertThat;
65
+ import static org.msgpack.value.ValueFactory.newMap;
66
+ import static org.msgpack.value.ValueFactory.newString;
66
67
 
67
68
  public class TestSftpFileOutputPlugin
68
69
  {
@@ -80,6 +81,8 @@ public class TestSftpFileOutputPlugin
80
81
  private SshServer sshServer;
81
82
  private static final String HOST = "127.0.0.1";
82
83
  private static final int PORT = 20022;
84
+ private static final String PROXY_HOST = "127.0.0.1";
85
+ private static final int PROXY_PORT = 8080;
83
86
  private static final String USERNAME = "username";
84
87
  private static final String PASSWORD = "password";
85
88
  private static final String SECRET_KEY_FILE = Resources.getResource("id_rsa").getPath();
@@ -90,6 +93,7 @@ public class TestSftpFileOutputPlugin
90
93
  .add("_c2", DOUBLE)
91
94
  .add("_c3", STRING)
92
95
  .add("_c4", TIMESTAMP)
96
+ .add("_c5", JSON)
93
97
  .build();
94
98
 
95
99
  @Before
@@ -100,13 +104,18 @@ public class TestSftpFileOutputPlugin
100
104
  SftpFileOutputPlugin sftpFileOutputPlugin = new SftpFileOutputPlugin();
101
105
  runner = new FileOutputRunner(sftpFileOutputPlugin);
102
106
 
107
+ sshServer = createSshServer(HOST, PORT, USERNAME, PASSWORD);
108
+ }
109
+
110
+ private SshServer createSshServer(String host, int port, final String sshUsername, final String sshPassword)
111
+ {
103
112
  // setup a mock sftp server
104
- sshServer = SshServer.setUpDefaultServer();
113
+ SshServer sshServer = SshServer.setUpDefaultServer();
105
114
  VirtualFileSystemFactory fsFactory = new VirtualFileSystemFactory();
106
- fsFactory.setUserHomeDir(USERNAME, testFolder.getRoot().getAbsolutePath());
115
+ fsFactory.setUserHomeDir(sshUsername, testFolder.getRoot().toPath());
107
116
  sshServer.setFileSystemFactory(fsFactory);
108
- sshServer.setHost(HOST);
109
- sshServer.setPort(PORT);
117
+ sshServer.setHost(host);
118
+ sshServer.setPort(port);
110
119
  sshServer.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystemFactory()));
111
120
  sshServer.setCommandFactory(new ScpCommandFactory());
112
121
  sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
@@ -115,7 +124,7 @@ public class TestSftpFileOutputPlugin
115
124
  @Override
116
125
  public boolean authenticate(final String username, final String password, final ServerSession session)
117
126
  {
118
- return USERNAME.contentEquals(username) && PASSWORD.contentEquals(password);
127
+ return sshUsername.contentEquals(username) && sshPassword.contentEquals(password);
119
128
  }
120
129
  });
121
130
  sshServer.setPublickeyAuthenticator(new PublickeyAuthenticator()
@@ -133,10 +142,19 @@ public class TestSftpFileOutputPlugin
133
142
  catch (IOException e) {
134
143
  logger.debug(e.getMessage(), e);
135
144
  }
145
+ return sshServer;
146
+ }
147
+
148
+ private HttpProxyServer createProxyServer(int port)
149
+ {
150
+ return DefaultHttpProxyServer.bootstrap()
151
+ .withPort(port)
152
+ .start();
136
153
  }
137
154
 
138
155
  @After
139
- public void cleanup() throws InterruptedException {
156
+ public void cleanup() throws InterruptedException
157
+ {
140
158
  try {
141
159
  sshServer.stop(true);
142
160
  }
@@ -151,17 +169,19 @@ public class TestSftpFileOutputPlugin
151
169
  return loader.fromYamlString(yaml);
152
170
  }
153
171
 
154
- private List<String> lsR(List<String> fileNames, Path dir) {
172
+ private List<String> lsR(List<String> fileNames, Path dir)
173
+ {
155
174
  try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
156
175
  for (Path path : stream) {
157
- if(path.toFile().isDirectory()) {
176
+ if (path.toFile().isDirectory()) {
158
177
  lsR(fileNames, path);
159
- } else {
178
+ }
179
+ else {
160
180
  fileNames.add(path.toAbsolutePath().toString());
161
181
  }
162
182
  }
163
183
  }
164
- catch(IOException e) {
184
+ catch (IOException e) {
165
185
  logger.debug(e.getMessage(), e);
166
186
  }
167
187
  return fileNames;
@@ -179,12 +199,12 @@ public class TestSftpFileOutputPlugin
179
199
  boolean committed = false;
180
200
  try {
181
201
  // Result:
182
- // _c0,_c1,_c2,_c3,_c4
183
- // true,2,3.0,45,1970-01-01 00:00:00.678000 +0000
184
- // true,2,3.0,45,1970-01-01 00:00:00.678000 +0000
185
- for (Page page : PageTestUtils.buildPage(runtime.getBufferAllocator(), SCHEMA, true, 2L, 3.0D, "45",
186
- Timestamp.ofEpochMilli(678L), true, 2L, 3.0D, "45",
187
- Timestamp.ofEpochMilli(678L))) {
202
+ // _c0,_c1,_c2,_c3,_c4,_c5
203
+ // true,2,3.0,45,1970-01-01 00:00:00.678000 +0000,{\"k\":\"v\"}
204
+ // true,2,3.0,45,1970-01-01 00:00:00.678000 +0000,{\"k\":\"v\"}
205
+ for (Page page : PageTestUtils.buildPage(runtime.getBufferAllocator(), SCHEMA,
206
+ true, 2L, 3.0D, "45", Timestamp.ofEpochMilli(678L), newMap(newString("k"), newString("v")),
207
+ true, 2L, 3.0D, "45", Timestamp.ofEpochMilli(678L), newMap(newString("k"), newString("v")))) {
188
208
  pageOutput.add(page);
189
209
  if (sleep.isPresent()) {
190
210
  Thread.sleep(sleep.get() * 1000);
@@ -215,7 +235,7 @@ public class TestSftpFileOutputPlugin
215
235
  for (int i = 0; i < lines.size(); i++) {
216
236
  String[] record = lines.get(i).split(",");
217
237
  if (i == 0) {
218
- for (int j = 0; j <= 4 ; j++) {
238
+ for (int j = 0; j <= 4; j++) {
219
239
  assertEquals("_c" + j, record[j]);
220
240
  }
221
241
  }
@@ -226,6 +246,7 @@ public class TestSftpFileOutputPlugin
226
246
  assertEquals("3.0", record[2]);
227
247
  assertEquals("45", record[3]);
228
248
  assertEquals("1970-01-01 00:00:00.678000 +0000", record[4]);
249
+ assertEquals("{\"k\":\"v\"}", record[5]);
229
250
  }
230
251
  }
231
252
  }
@@ -272,6 +293,49 @@ public class TestSftpFileOutputPlugin
272
293
  assertEquals(pathPrefix, task.getPathPrefix());
273
294
  assertEquals("txt", task.getFileNameExtension());
274
295
  assertEquals("%03d.%02d.", task.getSequenceFormat());
296
+ assertEquals(Optional.absent(), task.getProxy());
297
+ }
298
+
299
+ @Test
300
+ public void testConfigValuesIncludingProxy()
301
+ {
302
+ // setting embulk config
303
+ final String pathPrefix = "/test/testUserPassword";
304
+ String configYaml = "" +
305
+ "type: sftp\n" +
306
+ "host: " + HOST + "\n" +
307
+ "user: " + USERNAME + "\n" +
308
+ "path_prefix: " + pathPrefix + "\n" +
309
+ "file_ext: txt\n" +
310
+ "proxy: \n" +
311
+ " type: http\n" +
312
+ " host: proxy_host\n" +
313
+ " port: 80 \n" +
314
+ " user: proxy_user\n" +
315
+ " password: proxy_pass\n" +
316
+ " command: proxy_command\n" +
317
+ "formatter:\n" +
318
+ " type: csv\n" +
319
+ " newline: CRLF\n" +
320
+ " newline_in_field: LF\n" +
321
+ " header_line: true\n" +
322
+ " charset: UTF-8\n" +
323
+ " quote_policy: NONE\n" +
324
+ " quote: \"\\\"\"\n" +
325
+ " escape: \"\\\\\"\n" +
326
+ " null_string: \"\"\n" +
327
+ " default_timezone: 'UTC'";
328
+
329
+ ConfigSource config = getConfigFromYaml(configYaml);
330
+ PluginTask task = config.loadConfig(PluginTask.class);
331
+
332
+ ProxyTask proxy = task.getProxy().get();
333
+ assertEquals("proxy_command", proxy.getCommand().get());
334
+ assertEquals("proxy_host", proxy.getHost().get());
335
+ assertEquals("proxy_user", proxy.getUser().get());
336
+ assertEquals("proxy_pass", proxy.getPassword().get());
337
+ assertEquals(80, proxy.getPort());
338
+ assertEquals(ProxyTask.ProxyType.HTTP, proxy.getType());
275
339
  }
276
340
 
277
341
  // Cases
@@ -284,7 +348,6 @@ public class TestSftpFileOutputPlugin
284
348
  // timeout
285
349
  // 0 second
286
350
 
287
-
288
351
  @Test
289
352
  public void testUserPasswordAndPutToUserDirectoryRoot()
290
353
  {
@@ -318,7 +381,6 @@ public class TestSftpFileOutputPlugin
318
381
  assertRecordsInFile(String.format("%s/%s001.00.txt",
319
382
  testFolder.getRoot().getAbsolutePath(),
320
383
  pathPrefix));
321
-
322
384
  }
323
385
 
324
386
  @Test
@@ -358,6 +420,60 @@ public class TestSftpFileOutputPlugin
358
420
  pathPrefix));
359
421
  }
360
422
 
423
+ @Test
424
+ public void testUserSecretKeyFileWithProxy()
425
+ {
426
+ HttpProxyServer proxyServer = null;
427
+ try {
428
+ proxyServer = createProxyServer(PROXY_PORT);
429
+
430
+ // setting embulk config
431
+ final String pathPrefix = "/test/testUserPassword";
432
+ String configYaml = "" +
433
+ "type: sftp\n" +
434
+ "host: " + HOST + "\n" +
435
+ "port: " + PORT + "\n" +
436
+ "user: " + USERNAME + "\n" +
437
+ "secret_key_file: " + SECRET_KEY_FILE + "\n" +
438
+ "secret_key_passphrase: " + SECRET_KEY_PASSPHRASE + "\n" +
439
+ "path_prefix: " + testFolder.getRoot().getAbsolutePath() + pathPrefix + "\n" +
440
+ "file_ext: txt\n" +
441
+ "proxy: \n" +
442
+ " type: http\n" +
443
+ " host: " + PROXY_HOST + "\n" +
444
+ " port: " + PROXY_PORT + " \n" +
445
+ " user: " + USERNAME + "\n" +
446
+ " password: " + PASSWORD + "\n" +
447
+ " command: \n" +
448
+ "formatter:\n" +
449
+ " type: csv\n" +
450
+ " newline: CRLF\n" +
451
+ " newline_in_field: LF\n" +
452
+ " header_line: true\n" +
453
+ " charset: UTF-8\n" +
454
+ " quote_policy: NONE\n" +
455
+ " quote: \"\\\"\"\n" +
456
+ " escape: \"\\\\\"\n" +
457
+ " null_string: \"\"\n" +
458
+ " default_timezone: 'UTC'";
459
+
460
+ // runner.transaction -> ...
461
+ run(configYaml, Optional.<Integer>absent());
462
+
463
+ List<String> fileList = lsR(Lists.<String>newArrayList(), Paths.get(testFolder.getRoot().getAbsolutePath()));
464
+ assertThat(fileList, hasItem(containsString(pathPrefix + "001.00.txt")));
465
+
466
+ assertRecordsInFile(String.format("%s/%s001.00.txt",
467
+ testFolder.getRoot().getAbsolutePath(),
468
+ pathPrefix));
469
+ }
470
+ finally {
471
+ if (proxyServer != null) {
472
+ proxyServer.stop();
473
+ }
474
+ }
475
+ }
476
+
361
477
  @Test
362
478
  public void testTimeout()
363
479
  {
@@ -393,4 +509,30 @@ public class TestSftpFileOutputPlugin
393
509
  // runner.transaction -> ...
394
510
  run(configYaml, Optional.of(60)); // sleep 1 minute while processing
395
511
  }
512
+
513
+ @Test
514
+ public void testProxyType()
515
+ {
516
+ // test valueOf()
517
+ assertEquals("http", ProxyTask.ProxyType.valueOf("HTTP").toString());
518
+ assertEquals("socks", ProxyTask.ProxyType.valueOf("SOCKS").toString());
519
+ assertEquals("stream", ProxyTask.ProxyType.valueOf("STREAM").toString());
520
+ try {
521
+ ProxyTask.ProxyType.valueOf("non-existing-type");
522
+ }
523
+ catch (Exception e) {
524
+ assertEquals(IllegalArgumentException.class, e.getClass());
525
+ }
526
+
527
+ // test fromString
528
+ assertEquals(ProxyTask.ProxyType.HTTP, ProxyTask.ProxyType.fromString("http"));
529
+ assertEquals(ProxyTask.ProxyType.SOCKS, ProxyTask.ProxyType.fromString("socks"));
530
+ assertEquals(ProxyTask.ProxyType.STREAM, ProxyTask.ProxyType.fromString("stream"));
531
+ try {
532
+ ProxyTask.ProxyType.fromString("non-existing-type");
533
+ }
534
+ catch (Exception e) {
535
+ assertEquals(ConfigException.class, e.getClass());
536
+ }
537
+ }
396
538
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-sftp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Civitaspo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-28 00:00:00.000000000 Z
11
+ date: 2016-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -47,9 +47,12 @@ extra_rdoc_files: []
47
47
  files:
48
48
  - .gitignore
49
49
  - .travis.yml
50
+ - CHANGELOG.md
50
51
  - LICENSE.txt
51
52
  - README.md
52
53
  - build.gradle
54
+ - config/checkstyle/checkstyle.xml
55
+ - config/checkstyle/default.xml
53
56
  - example/data.csv
54
57
  - example/sample.yml
55
58
  - gradle/wrapper/gradle-wrapper.jar
@@ -57,6 +60,7 @@ files:
57
60
  - gradlew
58
61
  - gradlew.bat
59
62
  - lib/embulk/output/sftp.rb
63
+ - src/main/java/org/embulk/output/sftp/ProxyTask.java
60
64
  - src/main/java/org/embulk/output/sftp/SftpFileOutput.java
61
65
  - src/main/java/org/embulk/output/sftp/SftpFileOutputPlugin.java
62
66
  - src/test/java/org/embulk/output/sftp/TestSftpFileOutputPlugin.java
@@ -64,7 +68,7 @@ files:
64
68
  - src/test/resources/id_rsa.pub
65
69
  - classpath/commons-logging-1.2.jar
66
70
  - classpath/commons-vfs2-2.1.1660580.2.jar
67
- - classpath/embulk-output-sftp-0.0.4.jar
71
+ - classpath/embulk-output-sftp-0.0.5.jar
68
72
  - classpath/jsch-0.1.53.jar
69
73
  homepage: https://github.com/civitaspo/embulk-output-sftp
70
74
  licenses:
Binary file