embulk-input-gcs 0.3.0 → 0.3.1
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 +5 -5
- data/.travis.yml +4 -4
- data/CHANGELOG.md +4 -0
- data/build.gradle +41 -12
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +2 -2
- data/gradlew +41 -33
- data/gradlew.bat +4 -10
- data/src/main/java/org/embulk/input/gcs/AuthUtils.java +108 -0
- data/src/main/java/org/embulk/input/gcs/FileList.java +12 -9
- data/src/main/java/org/embulk/input/gcs/GcsFileInput.java +46 -126
- data/src/main/java/org/embulk/input/gcs/GcsFileInputPlugin.java +3 -38
- data/src/main/java/org/embulk/input/gcs/PluginTask.java +1 -29
- data/src/main/java/org/embulk/input/gcs/RetryUtils.java +153 -0
- data/src/main/java/org/embulk/input/gcs/SingleFileProvider.java +30 -63
- data/src/test/java/org/embulk/input/gcs/TestAuthUtils.java +153 -0
- data/src/test/java/org/embulk/input/gcs/TestGcsFileInputPlugin.java +42 -94
- data/src/test/java/org/embulk/input/gcs/TestInputStreamReopener.java +145 -0
- data/src/test/java/org/embulk/input/gcs/TestRetryUtils.java +164 -0
- data/src/test/resources/secrets.tar.enc +0 -0
- metadata +53 -28
- data/secretkeys.tar +0 -0
- data/secretkeys.tar.enc +0 -0
- data/src/main/java/org/embulk/input/gcs/GcsAuthentication.java +0 -206
- data/src/test/java/org/embulk/input/gcs/TestGcsAuthentication.java +0 -185
- data/src/test/resources/secretkeys.tar.enc +0 -0
@@ -1,23 +1,19 @@
|
|
1
1
|
package org.embulk.input.gcs;
|
2
2
|
|
3
|
-
import com.google.
|
4
|
-
import com.google.
|
5
|
-
import com.google.common.base.Throwables;
|
3
|
+
import com.google.cloud.ReadChannel;
|
4
|
+
import com.google.cloud.storage.Storage;
|
6
5
|
import org.embulk.spi.Exec;
|
7
6
|
import org.embulk.spi.util.InputStreamFileInput;
|
8
7
|
import org.embulk.spi.util.InputStreamFileInput.InputStreamWithHints;
|
9
|
-
import org.embulk.spi.util.
|
8
|
+
import org.embulk.spi.util.ResumableInputStream;
|
10
9
|
import org.slf4j.Logger;
|
11
10
|
|
12
|
-
import java.io.BufferedInputStream;
|
13
|
-
import java.io.BufferedOutputStream;
|
14
|
-
import java.io.File;
|
15
|
-
import java.io.FileInputStream;
|
16
|
-
import java.io.FileOutputStream;
|
17
11
|
import java.io.IOException;
|
12
|
+
import java.io.InputStream;
|
13
|
+
import java.nio.channels.Channels;
|
18
14
|
import java.util.Iterator;
|
19
15
|
|
20
|
-
import static
|
16
|
+
import static java.lang.String.format;
|
21
17
|
|
22
18
|
public class SingleFileProvider
|
23
19
|
implements InputStreamFileInput.Provider
|
@@ -25,20 +21,17 @@ public class SingleFileProvider
|
|
25
21
|
private final Storage client;
|
26
22
|
private final String bucket;
|
27
23
|
private final Iterator<String> iterator;
|
28
|
-
private final int maxConnectionRetry;
|
29
24
|
private boolean opened = false;
|
30
|
-
private final Logger log = Exec.getLogger(SingleFileProvider.class);
|
31
25
|
|
32
|
-
|
26
|
+
SingleFileProvider(PluginTask task, int taskIndex)
|
33
27
|
{
|
34
|
-
this.client =
|
28
|
+
this.client = AuthUtils.newClient(task);
|
35
29
|
this.bucket = task.getBucket();
|
36
30
|
this.iterator = task.getFiles().get(taskIndex).iterator();
|
37
|
-
this.maxConnectionRetry = task.getMaxConnectionRetry();
|
38
31
|
}
|
39
32
|
|
40
33
|
@Override
|
41
|
-
public InputStreamWithHints openNextWithHints()
|
34
|
+
public InputStreamWithHints openNextWithHints()
|
42
35
|
{
|
43
36
|
if (opened) {
|
44
37
|
return null;
|
@@ -48,10 +41,9 @@ public class SingleFileProvider
|
|
48
41
|
return null;
|
49
42
|
}
|
50
43
|
String key = iterator.next();
|
51
|
-
|
52
|
-
getRemoteContentsWithRetry(tempFile, client, bucket, key, maxConnectionRetry);
|
44
|
+
ReadChannel ch = client.get(bucket, key).reader();
|
53
45
|
return new InputStreamWithHints(
|
54
|
-
new
|
46
|
+
new ResumableInputStream(Channels.newInputStream(ch), new InputStreamReopener(client, bucket, key)),
|
55
47
|
String.format("gcs://%s/%s", bucket, key)
|
56
48
|
);
|
57
49
|
}
|
@@ -61,53 +53,28 @@ public class SingleFileProvider
|
|
61
53
|
{
|
62
54
|
}
|
63
55
|
|
64
|
-
|
56
|
+
static class InputStreamReopener
|
57
|
+
implements ResumableInputStream.Reopener
|
65
58
|
{
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
.withMaxRetryWait(30 * 1000)
|
71
|
-
.runInterruptible(new RetryExecutor.Retryable<Void>() {
|
72
|
-
@Override
|
73
|
-
public Void call() throws IOException
|
74
|
-
{
|
75
|
-
Storage.Objects.Get getObject = client.objects().get(bucket, key);
|
76
|
-
try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(tempFile))) {
|
77
|
-
IOUtils.copy(getObject.executeMediaAsInputStream(), outputStream);
|
78
|
-
}
|
79
|
-
return null;
|
80
|
-
}
|
59
|
+
private Logger logger = Exec.getLogger(getClass());
|
60
|
+
private final Storage client;
|
61
|
+
private final String bucket;
|
62
|
+
private final String key;
|
81
63
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
@Override
|
89
|
-
public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
|
90
|
-
throws RetryExecutor.RetryGiveupException
|
91
|
-
{
|
92
|
-
String message = String.format("GCS GET request failed. Retrying %d/%d after %d seconds. Message: %s",
|
93
|
-
retryCount, retryLimit, retryWait / 1000, exception.getMessage());
|
94
|
-
if (retryCount % 3 == 0) {
|
95
|
-
log.warn(message, exception);
|
96
|
-
}
|
97
|
-
else {
|
98
|
-
log.warn(message);
|
99
|
-
}
|
100
|
-
}
|
101
|
-
|
102
|
-
@Override
|
103
|
-
public void onGiveup(Exception firstException, Exception lastException)
|
104
|
-
throws RetryExecutor.RetryGiveupException
|
105
|
-
{
|
106
|
-
}
|
107
|
-
});
|
64
|
+
InputStreamReopener(Storage client, String bucket, String key)
|
65
|
+
{
|
66
|
+
this.client = client;
|
67
|
+
this.bucket = bucket;
|
68
|
+
this.key = key;
|
108
69
|
}
|
109
|
-
|
110
|
-
|
70
|
+
|
71
|
+
@Override
|
72
|
+
public InputStream reopen(long offset, Exception closedCause) throws IOException
|
73
|
+
{
|
74
|
+
logger.warn(format("GCS read failed. Retrying GET request with %,d bytes offset", offset), closedCause);
|
75
|
+
ReadChannel ch = client.get(bucket, key).reader();
|
76
|
+
ch.seek(offset);
|
77
|
+
return Channels.newInputStream(ch);
|
111
78
|
}
|
112
79
|
}
|
113
80
|
}
|
@@ -0,0 +1,153 @@
|
|
1
|
+
package org.embulk.input.gcs;
|
2
|
+
|
3
|
+
import com.google.auth.Credentials;
|
4
|
+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
5
|
+
import org.embulk.EmbulkTestRuntime;
|
6
|
+
import org.embulk.config.ConfigException;
|
7
|
+
import org.embulk.config.ConfigSource;
|
8
|
+
import org.embulk.spi.Exec;
|
9
|
+
import org.embulk.spi.unit.LocalFile;
|
10
|
+
import org.junit.Before;
|
11
|
+
import org.junit.BeforeClass;
|
12
|
+
import org.junit.Rule;
|
13
|
+
import org.junit.Test;
|
14
|
+
import org.mockito.Mockito;
|
15
|
+
|
16
|
+
import java.io.FileNotFoundException;
|
17
|
+
import java.io.IOException;
|
18
|
+
import java.nio.file.Path;
|
19
|
+
import java.security.GeneralSecurityException;
|
20
|
+
import java.util.Optional;
|
21
|
+
|
22
|
+
import static org.hamcrest.CoreMatchers.instanceOf;
|
23
|
+
import static org.junit.Assert.assertThat;
|
24
|
+
import static org.junit.Assume.assumeNotNull;
|
25
|
+
|
26
|
+
public class TestAuthUtils
|
27
|
+
{
|
28
|
+
private static Optional<String> GCP_EMAIL;
|
29
|
+
private static Optional<String> GCP_P12_KEYFILE;
|
30
|
+
private static Optional<String> GCP_JSON_KEYFILE;
|
31
|
+
private static String GCP_BUCKET;
|
32
|
+
private static final String GCP_APPLICATION_NAME = "embulk-input-gcs";
|
33
|
+
|
34
|
+
/*
|
35
|
+
* This test case requires environment variables
|
36
|
+
* GCP_EMAIL
|
37
|
+
* GCP_P12_KEYFILE
|
38
|
+
* GCP_JSON_KEYFILE
|
39
|
+
* GCP_BUCKET
|
40
|
+
*/
|
41
|
+
@BeforeClass
|
42
|
+
public static void initializeConstant()
|
43
|
+
{
|
44
|
+
String gcpEmail = System.getenv("GCP_EMAIL");
|
45
|
+
String gcpP12KeyFile = System.getenv("GCP_P12_KEYFILE");
|
46
|
+
String gcpJsonKeyFile = System.getenv("GCP_JSON_KEYFILE");
|
47
|
+
String gcpBucket = System.getenv("GCP_BUCKET");
|
48
|
+
|
49
|
+
// skip test cases, if environment variables are not set.
|
50
|
+
assumeNotNull(gcpEmail, gcpP12KeyFile, gcpJsonKeyFile, gcpBucket);
|
51
|
+
|
52
|
+
GCP_EMAIL = Optional.of(gcpEmail);
|
53
|
+
GCP_P12_KEYFILE = Optional.of(gcpP12KeyFile);
|
54
|
+
GCP_JSON_KEYFILE = Optional.of(gcpJsonKeyFile);
|
55
|
+
GCP_BUCKET = gcpBucket;
|
56
|
+
}
|
57
|
+
|
58
|
+
@SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
|
59
|
+
@Rule
|
60
|
+
public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
|
61
|
+
private ConfigSource config;
|
62
|
+
|
63
|
+
@Before
|
64
|
+
public void setUp()
|
65
|
+
{
|
66
|
+
config = config();
|
67
|
+
}
|
68
|
+
|
69
|
+
@Test
|
70
|
+
public void testGetServiceAccountCredentialSuccess() throws IOException, GeneralSecurityException
|
71
|
+
{
|
72
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
73
|
+
assertThat(AuthUtils.fromP12(task), instanceOf(Credentials.class));
|
74
|
+
}
|
75
|
+
|
76
|
+
@Test(expected = FileNotFoundException.class)
|
77
|
+
public void testGetServiceAccountCredentialThrowFileNotFoundException()
|
78
|
+
throws IOException, GeneralSecurityException
|
79
|
+
{
|
80
|
+
Path mockNotFound = Mockito.mock(Path.class);
|
81
|
+
Mockito.when(mockNotFound.toString()).thenReturn("/path/to/notfound.p12");
|
82
|
+
LocalFile p12File = Mockito.mock(LocalFile.class);
|
83
|
+
Mockito.doReturn(mockNotFound).when(p12File).getPath();
|
84
|
+
|
85
|
+
PluginTask task = Mockito.mock(PluginTask.class);
|
86
|
+
Mockito.doReturn(Optional.of(p12File)).when(task).getP12Keyfile();
|
87
|
+
AuthUtils.fromP12(task);
|
88
|
+
}
|
89
|
+
|
90
|
+
@Test
|
91
|
+
public void testGetGcsClientUsingServiceAccountCredentialSuccess()
|
92
|
+
{
|
93
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
94
|
+
assertThat(AuthUtils.newClient(task), instanceOf(com.google.cloud.storage.Storage.class));
|
95
|
+
}
|
96
|
+
|
97
|
+
@Test(expected = ConfigException.class)
|
98
|
+
public void testGetGcsClientUsingServiceAccountCredentialThrowJsonResponseException()
|
99
|
+
{
|
100
|
+
PluginTask task = config.set("bucket", "non-exists-bucket")
|
101
|
+
.loadConfig(PluginTask.class);
|
102
|
+
AuthUtils.newClient(task);
|
103
|
+
}
|
104
|
+
|
105
|
+
@Test
|
106
|
+
public void testGetServiceAccountCredentialFromJsonFileSuccess()
|
107
|
+
throws IOException
|
108
|
+
{
|
109
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
110
|
+
assertThat(AuthUtils.fromJson(task), instanceOf(Credentials.class));
|
111
|
+
}
|
112
|
+
|
113
|
+
@Test(expected = FileNotFoundException.class)
|
114
|
+
public void testGetServiceAccountCredentialFromJsonThrowFileFileNotFoundException()
|
115
|
+
throws IOException
|
116
|
+
{
|
117
|
+
Path mockNotFound = Mockito.mock(Path.class);
|
118
|
+
Mockito.when(mockNotFound.toString()).thenReturn("/path/to/notfound.json");
|
119
|
+
LocalFile jsonFile = Mockito.mock(LocalFile.class);
|
120
|
+
Mockito.doReturn(mockNotFound).when(jsonFile).getPath();
|
121
|
+
|
122
|
+
PluginTask task = Mockito.mock(PluginTask.class);
|
123
|
+
Mockito.doReturn(Optional.of(jsonFile)).when(task).getJsonKeyfile();
|
124
|
+
AuthUtils.fromJson(task);
|
125
|
+
}
|
126
|
+
|
127
|
+
@Test
|
128
|
+
public void testGetServiceAccountCredentialFromJsonSuccess()
|
129
|
+
{
|
130
|
+
PluginTask task = config.set("auth_method", AuthUtils.AuthMethod.json_key).loadConfig(PluginTask.class);
|
131
|
+
assertThat(AuthUtils.newClient(task), instanceOf(com.google.cloud.storage.Storage.class));
|
132
|
+
}
|
133
|
+
|
134
|
+
@Test(expected = ConfigException.class)
|
135
|
+
public void testGetServiceAccountCredentialFromJsonThrowGoogleJsonResponseException()
|
136
|
+
{
|
137
|
+
PluginTask task = config.set("auth_method", AuthUtils.AuthMethod.json_key)
|
138
|
+
.set("bucket", "non-exists-bucket")
|
139
|
+
.loadConfig(PluginTask.class);
|
140
|
+
AuthUtils.newClient(task);
|
141
|
+
}
|
142
|
+
|
143
|
+
private ConfigSource config()
|
144
|
+
{
|
145
|
+
return Exec.newConfigSource()
|
146
|
+
.set("bucket", GCP_BUCKET)
|
147
|
+
.set("auth_method", "private_key")
|
148
|
+
.set("service_account_email", GCP_EMAIL)
|
149
|
+
.set("p12_keyfile", GCP_P12_KEYFILE)
|
150
|
+
.set("json_keyfile", GCP_JSON_KEYFILE)
|
151
|
+
.set("application_name", GCP_APPLICATION_NAME);
|
152
|
+
}
|
153
|
+
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
package org.embulk.input.gcs;
|
2
2
|
|
3
|
-
import com.google.api.services.storage.Storage;
|
4
3
|
import com.google.common.collect.ImmutableList;
|
5
4
|
import com.google.common.collect.ImmutableMap;
|
6
5
|
import com.google.common.collect.Lists;
|
@@ -11,7 +10,6 @@ import org.embulk.config.ConfigSource;
|
|
11
10
|
import org.embulk.config.TaskReport;
|
12
11
|
import org.embulk.config.TaskSource;
|
13
12
|
import org.embulk.spi.Exec;
|
14
|
-
import org.embulk.spi.FileInputPlugin;
|
15
13
|
import org.embulk.spi.FileInputRunner;
|
16
14
|
import org.embulk.spi.InputPlugin;
|
17
15
|
import org.embulk.spi.Schema;
|
@@ -23,20 +21,15 @@ import org.junit.BeforeClass;
|
|
23
21
|
import org.junit.Rule;
|
24
22
|
import org.junit.Test;
|
25
23
|
|
26
|
-
import java.io.IOException;
|
27
|
-
import java.security.GeneralSecurityException;
|
28
24
|
import java.util.ArrayList;
|
29
25
|
import java.util.Arrays;
|
30
26
|
import java.util.List;
|
31
27
|
import java.util.Optional;
|
32
28
|
|
33
29
|
import static org.junit.Assert.assertEquals;
|
30
|
+
import static org.junit.Assert.assertTrue;
|
34
31
|
import static org.junit.Assume.assumeNotNull;
|
35
32
|
|
36
|
-
import java.lang.reflect.InvocationTargetException;
|
37
|
-
|
38
|
-
import java.lang.reflect.Method;
|
39
|
-
|
40
33
|
public class TestGcsFileInputPlugin
|
41
34
|
{
|
42
35
|
private static Optional<String> GCP_EMAIL;
|
@@ -45,8 +38,7 @@ public class TestGcsFileInputPlugin
|
|
45
38
|
private static String GCP_BUCKET;
|
46
39
|
private static String GCP_BUCKET_DIRECTORY;
|
47
40
|
private static String GCP_PATH_PREFIX;
|
48
|
-
private static String GCP_APPLICATION_NAME;
|
49
|
-
private static int MAX_CONNECTION_RETRY = 3;
|
41
|
+
private static String GCP_APPLICATION_NAME = "embulk-input-gcs";
|
50
42
|
private FileInputRunner runner;
|
51
43
|
private MockPageOutput output;
|
52
44
|
|
@@ -83,7 +75,7 @@ public class TestGcsFileInputPlugin
|
|
83
75
|
private GcsFileInputPlugin plugin;
|
84
76
|
|
85
77
|
@Before
|
86
|
-
public void createResources()
|
78
|
+
public void createResources()
|
87
79
|
{
|
88
80
|
config = config();
|
89
81
|
plugin = new GcsFileInputPlugin();
|
@@ -99,7 +91,7 @@ public class TestGcsFileInputPlugin
|
|
99
91
|
.set("path_prefix", "my-prefix");
|
100
92
|
|
101
93
|
PluginTask task = config.loadConfig(PluginTask.class);
|
102
|
-
|
94
|
+
assertTrue(task.getIncremental());
|
103
95
|
assertEquals("private_key", task.getAuthMethod().toString());
|
104
96
|
assertEquals("Embulk GCS input plugin", task.getApplicationName());
|
105
97
|
}
|
@@ -215,22 +207,15 @@ public class TestGcsFileInputPlugin
|
|
215
207
|
|
216
208
|
@Test
|
217
209
|
public void testGcsClientCreateSuccessfully()
|
218
|
-
throws GeneralSecurityException, IOException, NoSuchMethodException,
|
219
|
-
IllegalAccessException, InvocationTargetException
|
220
210
|
{
|
221
211
|
PluginTask task = config().loadConfig(PluginTask.class);
|
222
|
-
|
223
|
-
|
224
|
-
Method method = GcsFileInputPlugin.class.getDeclaredMethod("newGcsAuth", PluginTask.class);
|
225
|
-
method.setAccessible(true);
|
226
|
-
GcsFileInput.newGcsClient(task, (GcsAuthentication) method.invoke(plugin, task)); // no errors happens
|
212
|
+
AuthUtils.newClient(task);
|
227
213
|
}
|
228
214
|
|
229
215
|
@Test(expected = ConfigException.class)
|
230
216
|
public void testGcsClientCreateThrowConfigException()
|
231
|
-
throws GeneralSecurityException, IOException, NoSuchMethodException,
|
232
|
-
IllegalAccessException, InvocationTargetException
|
233
217
|
{
|
218
|
+
// verify AuthUtils#newClient() to throws ConfigException for non-exists-bucket
|
234
219
|
ConfigSource config = Exec.newConfigSource()
|
235
220
|
.set("bucket", "non-exists-bucket")
|
236
221
|
.set("path_prefix", "my-prefix")
|
@@ -240,11 +225,7 @@ public class TestGcsFileInputPlugin
|
|
240
225
|
.set("parser", parserConfig(schemaConfig()));
|
241
226
|
|
242
227
|
PluginTask task = config.loadConfig(PluginTask.class);
|
243
|
-
|
244
|
-
|
245
|
-
Method method = GcsFileInputPlugin.class.getDeclaredMethod("newGcsAuth", PluginTask.class);
|
246
|
-
method.setAccessible(true);
|
247
|
-
GcsFileInput.newGcsClient(task, (GcsAuthentication) method.invoke(plugin, task));
|
228
|
+
AuthUtils.newClient(task);
|
248
229
|
}
|
249
230
|
|
250
231
|
@Test
|
@@ -254,14 +235,7 @@ public class TestGcsFileInputPlugin
|
|
254
235
|
FileList.Builder builder = new FileList.Builder(config);
|
255
236
|
builder.add("in/aa/a", 1);
|
256
237
|
task.setFiles(builder.build());
|
257
|
-
ConfigDiff configDiff = plugin.resume(task.dump(), 0,
|
258
|
-
{
|
259
|
-
@Override
|
260
|
-
public List<TaskReport> run(TaskSource taskSource, int taskCount)
|
261
|
-
{
|
262
|
-
return emptyTaskReports(taskCount);
|
263
|
-
}
|
264
|
-
});
|
238
|
+
ConfigDiff configDiff = plugin.resume(task.dump(), 0, (taskSource, taskCount) -> emptyTaskReports(taskCount));
|
265
239
|
assertEquals("in/aa/a", configDiff.get(String.class, "last_path"));
|
266
240
|
}
|
267
241
|
|
@@ -269,12 +243,11 @@ public class TestGcsFileInputPlugin
|
|
269
243
|
public void testCleanup()
|
270
244
|
{
|
271
245
|
PluginTask task = config.loadConfig(PluginTask.class);
|
272
|
-
plugin.cleanup(task.dump(), 0, Lists
|
246
|
+
plugin.cleanup(task.dump(), 0, Lists.newArrayList()); // no errors happens
|
273
247
|
}
|
274
248
|
|
275
249
|
@Test
|
276
250
|
public void testListFilesByPrefix()
|
277
|
-
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
|
278
251
|
{
|
279
252
|
List<String> expected = Arrays.asList(
|
280
253
|
GCP_BUCKET_DIRECTORY + "sample_01.csv",
|
@@ -282,21 +255,12 @@ public class TestGcsFileInputPlugin
|
|
282
255
|
);
|
283
256
|
|
284
257
|
PluginTask task = config.loadConfig(PluginTask.class);
|
285
|
-
ConfigDiff configDiff = plugin.transaction(config,
|
286
|
-
|
287
|
-
|
288
|
-
{
|
289
|
-
assertEquals(2, taskCount);
|
290
|
-
return emptyTaskReports(taskCount);
|
291
|
-
}
|
258
|
+
ConfigDiff configDiff = plugin.transaction(config, (taskSource, taskCount) -> {
|
259
|
+
assertEquals(2, taskCount);
|
260
|
+
return emptyTaskReports(taskCount);
|
292
261
|
});
|
293
262
|
|
294
|
-
|
295
|
-
method.setAccessible(true);
|
296
|
-
Storage client = GcsFileInput.newGcsClient(task, (GcsAuthentication) method.invoke(plugin, task));
|
297
|
-
FileList.Builder builder = new FileList.Builder(config);
|
298
|
-
GcsFileInput.listGcsFilesByPrefix(builder, client, GCP_BUCKET, GCP_PATH_PREFIX, Optional.empty());
|
299
|
-
FileList fileList = builder.build();
|
263
|
+
FileList fileList = GcsFileInput.listFiles(task);
|
300
264
|
assertEquals(expected.get(0), fileList.get(0).get(0));
|
301
265
|
assertEquals(expected.get(1), fileList.get(1).get(0));
|
302
266
|
assertEquals(GCP_BUCKET_DIRECTORY + "sample_02.csv", configDiff.get(String.class, "last_path"));
|
@@ -304,7 +268,6 @@ public class TestGcsFileInputPlugin
|
|
304
268
|
|
305
269
|
@Test
|
306
270
|
public void testListFilesByPrefixWithPattern()
|
307
|
-
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
|
308
271
|
{
|
309
272
|
List<String> expected = Arrays.asList(
|
310
273
|
GCP_BUCKET_DIRECTORY + "sample_01.csv"
|
@@ -312,27 +275,18 @@ public class TestGcsFileInputPlugin
|
|
312
275
|
|
313
276
|
ConfigSource configWithPattern = config.deepCopy().set("path_match_pattern", "1");
|
314
277
|
PluginTask task = configWithPattern.loadConfig(PluginTask.class);
|
315
|
-
ConfigDiff configDiff = plugin.transaction(configWithPattern,
|
316
|
-
|
317
|
-
|
318
|
-
{
|
319
|
-
assertEquals(1, taskCount);
|
320
|
-
return emptyTaskReports(taskCount);
|
321
|
-
}
|
278
|
+
ConfigDiff configDiff = plugin.transaction(configWithPattern, (taskSource, taskCount) -> {
|
279
|
+
assertEquals(1, taskCount);
|
280
|
+
return emptyTaskReports(taskCount);
|
322
281
|
});
|
323
282
|
|
324
|
-
|
325
|
-
method.setAccessible(true);
|
326
|
-
Storage client = GcsFileInput.newGcsClient(task, (GcsAuthentication) method.invoke(plugin, task));
|
327
|
-
FileList.Builder builder = new FileList.Builder(configWithPattern);
|
328
|
-
GcsFileInput.listGcsFilesByPrefix(builder, client, GCP_BUCKET, GCP_PATH_PREFIX, Optional.empty());
|
329
|
-
FileList fileList = builder.build();
|
283
|
+
FileList fileList = GcsFileInput.listFiles(task);
|
330
284
|
assertEquals(expected.get(0), fileList.get(0).get(0));
|
331
285
|
assertEquals(GCP_BUCKET_DIRECTORY + "sample_01.csv", configDiff.get(String.class, "last_path"));
|
332
286
|
}
|
333
287
|
|
334
288
|
@Test
|
335
|
-
public void testListFilesByPrefixIncrementalFalse()
|
289
|
+
public void testListFilesByPrefixIncrementalFalse()
|
336
290
|
{
|
337
291
|
ConfigSource config = config().deepCopy()
|
338
292
|
.set("incremental", false);
|
@@ -342,22 +296,22 @@ public class TestGcsFileInputPlugin
|
|
342
296
|
assertEquals("{}", configDiff.toString());
|
343
297
|
}
|
344
298
|
|
345
|
-
@Test
|
299
|
+
@Test(expected = ConfigException.class)
|
346
300
|
public void testListFilesByPrefixNonExistsBucket()
|
347
|
-
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
|
348
301
|
{
|
349
|
-
PluginTask task = config
|
302
|
+
PluginTask task = config
|
303
|
+
.set("bucket", "non-exists-bucket")
|
304
|
+
.set("path_prefix", "prefix")
|
305
|
+
.loadConfig(PluginTask.class);
|
350
306
|
runner.transaction(config, new Control());
|
351
307
|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
FileList.Builder builder = new FileList.Builder(config);
|
356
|
-
GcsFileInput.listGcsFilesByPrefix(builder, client, "non-exists-bucket", "prefix", Optional.empty()); // no errors happens
|
308
|
+
// after refactoring, GcsFileInput#listFiles() won't accept initialized client
|
309
|
+
// hence, this test will throw ConfigException
|
310
|
+
GcsFileInput.listFiles(task);
|
357
311
|
}
|
358
312
|
|
359
313
|
@Test
|
360
|
-
public void testNonExistingFilesWithPathPrefix()
|
314
|
+
public void testNonExistingFilesWithPathPrefix()
|
361
315
|
{
|
362
316
|
ConfigSource config = Exec.newConfigSource()
|
363
317
|
.set("bucket", GCP_BUCKET)
|
@@ -394,7 +348,6 @@ public class TestGcsFileInputPlugin
|
|
394
348
|
|
395
349
|
@Test
|
396
350
|
public void testGcsFileInputByOpen()
|
397
|
-
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException
|
398
351
|
{
|
399
352
|
ConfigSource config = Exec.newConfigSource()
|
400
353
|
.set("bucket", GCP_BUCKET)
|
@@ -407,31 +360,24 @@ public class TestGcsFileInputPlugin
|
|
407
360
|
PluginTask task = config.loadConfig(PluginTask.class);
|
408
361
|
runner.transaction(config, new Control());
|
409
362
|
|
410
|
-
|
411
|
-
method.setAccessible(true);
|
412
|
-
Storage client = GcsFileInput.newGcsClient(task, (GcsAuthentication) method.invoke(plugin, task));
|
413
|
-
task.setFiles(GcsFileInput.listFiles(task, client));
|
363
|
+
task.setFiles(GcsFileInput.listFiles(task));
|
414
364
|
|
415
365
|
assertRecords(config, output);
|
416
366
|
}
|
417
367
|
|
418
368
|
@Test
|
419
369
|
public void testBase64()
|
420
|
-
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
|
421
370
|
{
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
assertEquals("
|
426
|
-
assertEquals("CgJjMg==", method.invoke(plugin, "c2"));
|
427
|
-
assertEquals("Cgh0ZXN0LmNzdg==", method.invoke(plugin, "test.csv"));
|
428
|
-
assertEquals("ChZnY3MtdGVzdC9zYW1wbGVfMDEuY3N2", method.invoke(plugin, "gcs-test/sample_01.csv"));
|
371
|
+
assertEquals("CgFj", GcsFileInput.base64Encode("c"));
|
372
|
+
assertEquals("CgJjMg==", GcsFileInput.base64Encode("c2"));
|
373
|
+
assertEquals("Cgh0ZXN0LmNzdg==", GcsFileInput.base64Encode("test.csv"));
|
374
|
+
assertEquals("ChZnY3MtdGVzdC9zYW1wbGVfMDEuY3N2", GcsFileInput.base64Encode("gcs-test/sample_01.csv"));
|
429
375
|
String params = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc127";
|
430
376
|
String expected = "Cn9jY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjMTI3";
|
431
|
-
assertEquals(expected,
|
377
|
+
assertEquals(expected, GcsFileInput.base64Encode(params));
|
432
378
|
}
|
433
379
|
|
434
|
-
|
380
|
+
private ConfigSource config()
|
435
381
|
{
|
436
382
|
return Exec.newConfigSource()
|
437
383
|
.set("bucket", GCP_BUCKET)
|
@@ -444,7 +390,7 @@ public class TestGcsFileInputPlugin
|
|
444
390
|
.set("parser", parserConfig(schemaConfig()));
|
445
391
|
}
|
446
392
|
|
447
|
-
static List<TaskReport> emptyTaskReports(int taskCount)
|
393
|
+
private static List<TaskReport> emptyTaskReports(int taskCount)
|
448
394
|
{
|
449
395
|
ImmutableList.Builder<TaskReport> reports = new ImmutableList.Builder<>();
|
450
396
|
for (int i = 0; i < taskCount; i++) {
|
@@ -525,11 +471,13 @@ public class TestGcsFileInputPlugin
|
|
525
471
|
|
526
472
|
private static String getDirectory(String dir)
|
527
473
|
{
|
528
|
-
if (dir != null
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
474
|
+
if (dir != null) {
|
475
|
+
if (!dir.endsWith("/")) {
|
476
|
+
dir = dir + "/";
|
477
|
+
}
|
478
|
+
if (dir.startsWith("/")) {
|
479
|
+
dir = dir.replaceFirst("/", "");
|
480
|
+
}
|
533
481
|
}
|
534
482
|
return dir;
|
535
483
|
}
|