embulk-input-gcs 0.1.7 → 0.1.8

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: 24b44f4db77ef29422e03052b58cdf67378d5a79
4
- data.tar.gz: 031a0686510df86a6b87780aa0da707cd7cd64cc
3
+ metadata.gz: 219d292e87e6a2b326144302280e10bba7e3ea2a
4
+ data.tar.gz: c7e6e1933bc1961e16f18c68022261e1948cd5bc
5
5
  SHA512:
6
- metadata.gz: eb5815752627aeef5c32de944d23e78c03313970e574f61e3706808bb4314643311e4d581ae2fc7589ede24e80ff53236cdd0defecbd647a2d382d26b3630dcc
7
- data.tar.gz: 5ce214a4e252f78bbc9a9215d3edcc0de671220e2f5f9697687e4b4ac0d9d05303a5a724f399ad1a8175a8a8d85bd50d977fc01af8a718e74cb50981e34b3b6d
6
+ metadata.gz: e09e566db719125bc872a33026c4dd15bb1b29bf3ad82ce75a5cdd1fc5c342e2c8c72179accd3b9fafecf8ca3945dd26c0e1cdc70036d3a82d509485c388e925
7
+ data.tar.gz: aa068f8ac05d9fafec71baa24d71f18b59096521277ce836a5b27c1f1c491d4aee8ffe004d71117d5d6d68482e6525071fbcb2da4f3ca30601c638582cf7d260
data/ChangeLog CHANGED
@@ -1,3 +1,7 @@
1
+ Release 0.1.8 - 2015-10-29
2
+
3
+ * Added unit tests
4
+
1
5
  Release 0.1.7 - 2015-10-06
2
6
 
3
7
  * Added new auth method - json_keyfile of GCP(Google Cloud Platform)'s service account
data/README.md CHANGED
@@ -136,7 +136,7 @@ in:
136
136
 
137
137
  On the other hand, you don't need to explicitly create a service account for embulk when you
138
138
  run embulk in Google Compute Engine. In this third authentication method, you need to
139
- add the API scope "https://www.googleapis.com/auth/bigquery" to the scope list of your
139
+ add the API scope "https://www.googleapis.com/auth/devstorage.read_only" to the scope list of your
140
140
  Compute Engine VM instance, then you can configure embulk like this.
141
141
 
142
142
  [Setting the scope of service account access for instances](https://cloud.google.com/compute/docs/authentication)
@@ -153,3 +153,52 @@ in:
153
153
  ./gradlew gem
154
154
  ```
155
155
 
156
+ ## Test
157
+
158
+ To run unit tests, we need to configure the following environment variables.
159
+
160
+ Additionally, following files will be needed to upload to existing GCS bucket.
161
+ * [sample_01.csv](./src/test/resources/sample_01.csv)
162
+ * [sample_02.csv](./src/test/resources/sample_02.csv)
163
+
164
+ When environment variables are not set, skip some test cases.
165
+
166
+ ```
167
+ GCP_EMAIL
168
+ GCP_P12_KEYFILE
169
+ GCP_JSON_KEYFILE
170
+ GCP_BUCKET
171
+ GCP_BUCKET_DIRECTORY(optional, if needed)
172
+ ```
173
+
174
+ If you're using Mac OS X El Capitan and GUI Applications(IDE), like as follows.
175
+ ```
176
+ $ vi ~/Library/LaunchAgents/environment.plist
177
+ <?xml version="1.0" encoding="UTF-8"?>
178
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
179
+ <plist version="1.0">
180
+ <dict>
181
+ <key>Label</key>
182
+ <string>my.startup</string>
183
+ <key>ProgramArguments</key>
184
+ <array>
185
+ <string>sh</string>
186
+ <string>-c</string>
187
+ <string>
188
+ launchctl setenv GCP_EMAIL ABCXYZ123ABCXYZ123.gserviceaccount.com
189
+ launchctl setenv GCP_P12_KEYFILE /path/to/p12_keyfile.p12
190
+ launchctl setenv GCP_JSON_KEYFILE /path/to/json_keyfile.json
191
+ launchctl setenv GCP_BUCKET my-bucket
192
+ launchctl setenv GCP_BUCKET_DIRECTORY unittests
193
+ </string>
194
+ </array>
195
+ <key>RunAtLoad</key>
196
+ <true/>
197
+ </dict>
198
+ </plist>
199
+
200
+ $ launchctl load ~/Library/LaunchAgents/environment.plist
201
+ $ launchctl getenv GCP_EMAIL //try to get value.
202
+
203
+ Then start your applications.
204
+ ```
data/build.gradle CHANGED
@@ -2,6 +2,7 @@ plugins {
2
2
  id "com.jfrog.bintray" version "1.1"
3
3
  id "com.github.jruby-gradle.base" version "0.1.5"
4
4
  id "java"
5
+ id "jacoco"
5
6
  }
6
7
  import com.github.jrubygradle.JRubyExec
7
8
  repositories {
@@ -15,16 +16,18 @@ configurations {
15
16
  sourceCompatibility = 1.7
16
17
  targetCompatibility = 1.7
17
18
 
18
- version = "0.1.7"
19
+ version = "0.1.8"
19
20
 
20
21
  dependencies {
21
- compile "org.embulk:embulk-core:0.7.1"
22
- provided "org.embulk:embulk-core:0.7.1"
22
+ compile "org.embulk:embulk-core:0.7.5"
23
+ provided "org.embulk:embulk-core:0.7.5"
23
24
 
24
25
  compile "com.google.http-client:google-http-client-jackson2:1.19.0"
25
26
  compile ("com.google.apis:google-api-services-storage:v1-rev27-1.19.1") {exclude module: "guava-jdk5"}
26
27
 
27
- testCompile "junit:junit:4.+"
28
+ testCompile "junit:junit:4.12"
29
+ testCompile "org.embulk:embulk-core:0.7.5:tests"
30
+ testCompile "org.embulk:embulk-standards:0.7.5"
28
31
  }
29
32
 
30
33
  task classpath(type: Copy, dependsOn: ["jar"]) {
@@ -165,7 +165,7 @@ public class GcsFileInputPlugin
165
165
  {
166
166
  }
167
167
 
168
- private static Storage newGcsClient(final PluginTask task)
168
+ protected Storage newGcsClient(final PluginTask task)
169
169
  {
170
170
  Storage client = null;
171
171
  try {
@@ -213,12 +213,11 @@ public class GcsFileInputPlugin
213
213
  Storage.Buckets.Get getBucket = client.buckets().get(bucket);
214
214
  getBucket.setProjection("full");
215
215
  Bucket bk = getBucket.execute();
216
- if (log.isDebugEnabled()) {
217
- log.debug("bucket name: " + bucket);
218
- log.debug("bucket location: " + bk.getLocation());
219
- log.debug("bucket timeCreated: " + bk.getTimeCreated());
220
- log.debug("bucket owner: " + bk.getOwner());
221
- }
216
+
217
+ log.debug("bucket name: " + bucket);
218
+ log.debug("bucket location: " + bk.getLocation());
219
+ log.debug("bucket timeCreated: " + bk.getTimeCreated());
220
+ log.debug("bucket owner: " + bk.getOwner());
222
221
  } catch (IOException e) {
223
222
  log.warn("Could not access to bucket:" + bucket);
224
223
  log.warn(e.getMessage());
@@ -238,13 +237,11 @@ public class GcsFileInputPlugin
238
237
  break;
239
238
  }
240
239
  for (StorageObject o : items) {
241
- if (log.isDebugEnabled()) {
242
- log.debug("filename: " + o.getName());
243
- log.debug("updated: " + o.getUpdated());
244
- }
245
240
  if (o.getSize().compareTo(BigInteger.ZERO) > 0) {
246
241
  builder.add(o.getName());
247
242
  }
243
+ log.debug("filename: " + o.getName());
244
+ log.debug("updated: " + o.getUpdated());
248
245
  }
249
246
  lastKey = objects.getNextPageToken();
250
247
  listObjects.setPageToken(lastKey);
@@ -264,41 +261,10 @@ public class GcsFileInputPlugin
264
261
  return new GcsFileInput(task, taskIndex);
265
262
  }
266
263
 
267
- public static class GcsFileInput
264
+ public class GcsFileInput
268
265
  extends InputStreamFileInput
269
266
  implements TransactionalFileInput
270
267
  {
271
- private static class SingleFileProvider
272
- implements InputStreamFileInput.Provider
273
- {
274
- private final Storage client;
275
- private final String bucket;
276
- private final String key;
277
- private boolean opened = false;
278
-
279
- public SingleFileProvider(PluginTask task, int taskIndex)
280
- {
281
- this.client = newGcsClient(task);
282
- this.bucket = task.getBucket();
283
- this.key = task.getFiles().get(taskIndex);
284
- }
285
-
286
- @Override
287
- public InputStream openNext() throws IOException
288
- {
289
- if (opened) {
290
- return null;
291
- }
292
- opened = true;
293
- Storage.Objects.Get getObject = client.objects().get(bucket, key);
294
-
295
- return getObject.executeMediaAsInputStream();
296
- }
297
-
298
- @Override
299
- public void close() { }
300
- }
301
-
302
268
  public GcsFileInput(PluginTask task, int taskIndex)
303
269
  {
304
270
  super(task.getBufferAllocator(), new SingleFileProvider(task, taskIndex));
@@ -315,6 +281,37 @@ public class GcsFileInputPlugin
315
281
  public void close() { }
316
282
  }
317
283
 
284
+ private class SingleFileProvider
285
+ implements InputStreamFileInput.Provider
286
+ {
287
+ private final Storage client;
288
+ private final String bucket;
289
+ private final String key;
290
+ private boolean opened = false;
291
+
292
+ public SingleFileProvider(PluginTask task, int taskIndex)
293
+ {
294
+ this.client = newGcsClient(task);
295
+ this.bucket = task.getBucket();
296
+ this.key = task.getFiles().get(taskIndex);
297
+ }
298
+
299
+ @Override
300
+ public InputStream openNext() throws IOException
301
+ {
302
+ if (opened) {
303
+ return null;
304
+ }
305
+ opened = true;
306
+ Storage.Objects.Get getObject = client.objects().get(bucket, key);
307
+
308
+ return getObject.executeMediaAsInputStream();
309
+ }
310
+
311
+ @Override
312
+ public void close() { }
313
+ }
314
+
318
315
  public enum AuthMethod
319
316
  {
320
317
  private_key("private_key"),
@@ -0,0 +1,177 @@
1
+ package org.embulk.input.gcs;
2
+
3
+ import com.google.common.base.Optional;
4
+ import org.embulk.EmbulkTestRuntime;
5
+ import com.google.api.services.storage.Storage;
6
+ import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
7
+
8
+ import java.io.IOException;
9
+ import java.io.FileNotFoundException;
10
+ import java.security.GeneralSecurityException;
11
+ import com.google.api.client.googleapis.json.GoogleJsonResponseException;
12
+
13
+ import java.lang.reflect.Field;
14
+ import org.junit.BeforeClass;
15
+ import org.junit.Rule;
16
+ import org.junit.Test;
17
+ import static org.junit.Assert.assertEquals;
18
+ import static org.junit.Assume.assumeNotNull;
19
+
20
+ public class TestGcsAuthentication
21
+ {
22
+ private static Optional<String> GCP_EMAIL;
23
+ private static Optional<String> GCP_P12_KEYFILE;
24
+ private static Optional<String> GCP_JSON_KEYFILE;
25
+ private static String GCP_BUCKET;
26
+ private static final String GCP_APPLICATION_NAME = "embulk-input-gcs";
27
+
28
+ /*
29
+ * This test case requires environment variables
30
+ * GCP_EMAIL
31
+ * GCP_P12_KEYFILE
32
+ * GCP_JSON_KEYFILE
33
+ * GCP_BUCKET
34
+ */
35
+ @BeforeClass
36
+ public static void initializeConstant()
37
+ {
38
+ GCP_EMAIL = Optional.of(System.getenv("GCP_EMAIL"));
39
+ GCP_P12_KEYFILE = Optional.of(System.getenv("GCP_P12_KEYFILE"));
40
+ GCP_JSON_KEYFILE = Optional.of(System.getenv("GCP_JSON_KEYFILE"));
41
+ GCP_BUCKET = System.getenv("GCP_BUCKET");
42
+ // skip test cases, if environment variables are not set.
43
+ assumeNotNull(GCP_EMAIL, GCP_P12_KEYFILE, GCP_JSON_KEYFILE, GCP_BUCKET);
44
+ }
45
+
46
+ @Rule
47
+ public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
48
+
49
+ @Test
50
+ public void testGetServiceAccountCredentialSuccess()
51
+ throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
52
+ {
53
+ GcsAuthentication auth = new GcsAuthentication(
54
+ "private_key",
55
+ GCP_EMAIL,
56
+ GCP_P12_KEYFILE,
57
+ null,
58
+ GCP_APPLICATION_NAME
59
+ );
60
+
61
+ Field field = GcsAuthentication.class.getDeclaredField("credentials");
62
+ field.setAccessible(true);
63
+
64
+ assertEquals(GoogleCredential.class, field.get(auth).getClass());
65
+ }
66
+
67
+ @Test(expected = FileNotFoundException.class)
68
+ public void testGetServiceAccountCredentialThrowFileNotFoundException()
69
+ throws GeneralSecurityException, IOException
70
+ {
71
+ Optional<String> notFoundP12Keyfile = Optional.of("/path/to/notfound.p12");
72
+ GcsAuthentication auth = new GcsAuthentication(
73
+ "private_key",
74
+ GCP_EMAIL,
75
+ notFoundP12Keyfile,
76
+ null,
77
+ GCP_APPLICATION_NAME
78
+ );
79
+ }
80
+
81
+ @Test
82
+ public void testGetGcsClientUsingServiceAccountCredentialSuccess()
83
+ throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
84
+ {
85
+ GcsAuthentication auth = new GcsAuthentication(
86
+ "private_key",
87
+ GCP_EMAIL,
88
+ GCP_P12_KEYFILE,
89
+ null,
90
+ GCP_APPLICATION_NAME
91
+ );
92
+
93
+ Storage client = auth.getGcsClient(GCP_BUCKET);
94
+
95
+ assertEquals(Storage.class, client.getClass());
96
+ }
97
+
98
+ @Test(expected = GoogleJsonResponseException.class)
99
+ public void testGetGcsClientUsingServiceAccountCredentialThrowJsonResponseException()
100
+ throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
101
+ {
102
+ GcsAuthentication auth = new GcsAuthentication(
103
+ "private_key",
104
+ GCP_EMAIL,
105
+ GCP_P12_KEYFILE,
106
+ null,
107
+ GCP_APPLICATION_NAME
108
+ );
109
+
110
+ Storage client = auth.getGcsClient("non-exists-bucket");
111
+
112
+ assertEquals(Storage.class, client.getClass());
113
+ }
114
+
115
+ @Test
116
+ public void testGetServiceAccountCredentialFromJsonFileSuccess()
117
+ throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
118
+ {
119
+ GcsAuthentication auth = new GcsAuthentication(
120
+ "json_key",
121
+ GCP_EMAIL,
122
+ null,
123
+ GCP_JSON_KEYFILE,
124
+ GCP_APPLICATION_NAME
125
+ );
126
+ Field field = GcsAuthentication.class.getDeclaredField("credentials");
127
+ field.setAccessible(true);
128
+
129
+ assertEquals(GoogleCredential.class, field.get(auth).getClass());
130
+ }
131
+
132
+ @Test(expected = FileNotFoundException.class)
133
+ public void testGetServiceAccountCredentialFromJsonThrowFileFileNotFoundException()
134
+ throws GeneralSecurityException, IOException
135
+ {
136
+ Optional<String> notFoundJsonKeyfile = Optional.of("/path/to/notfound.json");
137
+ GcsAuthentication auth = new GcsAuthentication(
138
+ "json_key",
139
+ GCP_EMAIL,
140
+ null,
141
+ notFoundJsonKeyfile,
142
+ GCP_APPLICATION_NAME
143
+ );
144
+ }
145
+
146
+ @Test
147
+ public void testGetServiceAccountCredentialFromJsonSuccess()
148
+ throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
149
+ {
150
+ GcsAuthentication auth = new GcsAuthentication(
151
+ "json_key",
152
+ GCP_EMAIL,
153
+ null,
154
+ GCP_JSON_KEYFILE,
155
+ GCP_APPLICATION_NAME
156
+ );
157
+
158
+ Storage client = auth.getGcsClient(GCP_BUCKET);
159
+
160
+ assertEquals(Storage.class, client.getClass());
161
+ }
162
+
163
+ @Test(expected = GoogleJsonResponseException.class)
164
+ public void testGetServiceAccountCredentialFromJsonThrowGoogleJsonResponseException()
165
+ throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
166
+ {
167
+ GcsAuthentication auth = new GcsAuthentication(
168
+ "json_key",
169
+ GCP_EMAIL,
170
+ null,
171
+ GCP_JSON_KEYFILE,
172
+ GCP_APPLICATION_NAME
173
+ );
174
+
175
+ Storage client = auth.getGcsClient("non-exists-bucket");
176
+ }
177
+ }
@@ -1,9 +1,355 @@
1
1
  package org.embulk.input.gcs;
2
2
 
3
- import static org.junit.Assert.*;
3
+ import java.util.ArrayList;
4
+ import java.util.Arrays;
4
5
  import java.util.List;
6
+ import com.google.common.collect.ImmutableMap;
7
+ import com.google.common.base.Optional;
8
+ import com.google.common.collect.ImmutableList;
9
+ import com.google.common.collect.Lists;
10
+ import java.io.IOException;
11
+ import java.security.GeneralSecurityException;
12
+
13
+ import org.embulk.EmbulkTestRuntime;
14
+ import org.embulk.config.TaskReport;
15
+ import org.embulk.config.TaskSource;
16
+ import org.embulk.config.ConfigDiff;
17
+ import org.embulk.config.ConfigSource;
18
+ import org.embulk.config.ConfigException;
19
+ import org.embulk.spi.Exec;
20
+ import org.embulk.spi.FileInputPlugin;
21
+ import org.embulk.spi.FileInputRunner;
22
+ import org.embulk.spi.InputPlugin;
23
+ import org.embulk.spi.util.Pages;
24
+ import org.embulk.spi.Schema;
25
+ import org.embulk.spi.TestPageBuilderReader.MockPageOutput;
26
+ import org.embulk.input.gcs.GcsFileInputPlugin.PluginTask;
27
+ import org.embulk.standards.CsvParserPlugin;
28
+
29
+ import com.google.api.services.storage.Storage;
30
+
31
+ import org.junit.BeforeClass;
32
+ import org.junit.Before;
33
+ import org.junit.Rule;
5
34
  import org.junit.Test;
35
+ import static org.junit.Assert.assertEquals;
36
+ import static org.junit.Assume.assumeNotNull;
37
+
38
+ public class TestGcsFileInputPlugin
39
+ {
40
+ private static Optional<String> GCP_EMAIL;
41
+ private static Optional<String> GCP_P12_KEYFILE;
42
+ private static Optional<String> GCP_JSON_KEYFILE;
43
+ private static String GCP_BUCKET;
44
+ private static String GCP_BUCKET_DIRECTORY;
45
+ private static String GCP_PATH_PREFIX;
46
+ private final String GCP_APPLICATION_NAME = "embulk-input-gcs";
47
+ private FileInputRunner runner;
48
+ private MockPageOutput output;
49
+
50
+ /*
51
+ * This test case requires environment variables
52
+ * GCP_EMAIL
53
+ * GCP_P12_KEYFILE
54
+ * GCP_JSON_KEYFILE
55
+ * GCP_BUCKET
56
+ */
57
+ @BeforeClass
58
+ public static void initializeConstant()
59
+ {
60
+ GCP_EMAIL = Optional.of(System.getenv("GCP_EMAIL"));
61
+ GCP_P12_KEYFILE = Optional.of(System.getenv("GCP_P12_KEYFILE"));
62
+ GCP_JSON_KEYFILE = Optional.of(System.getenv("GCP_JSON_KEYFILE"));
63
+ GCP_BUCKET = System.getenv("GCP_BUCKET");
64
+ // skip test cases, if environment variables are not set.
65
+ assumeNotNull(GCP_EMAIL, GCP_P12_KEYFILE, GCP_JSON_KEYFILE, GCP_BUCKET);
66
+
67
+ GCP_BUCKET_DIRECTORY = System.getenv("GCP_BUCKET_DIRECTORY") != null ? getDirectory(System.getenv("GCP_BUCKET_DIRECTORY")) : getDirectory("");
68
+ GCP_PATH_PREFIX = GCP_BUCKET_DIRECTORY + "sample_";
69
+ }
70
+
71
+ @Rule
72
+ public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
73
+ private ConfigSource config;
74
+ private GcsFileInputPlugin plugin;
75
+
76
+ @Before
77
+ public void createResources() throws GeneralSecurityException, NoSuchMethodException, IOException
78
+ {
79
+ config = config();
80
+ plugin = new GcsFileInputPlugin();
81
+ runner = new FileInputRunner(runtime.getInstance(GcsFileInputPlugin.class));
82
+ output = new MockPageOutput();
83
+ }
84
+
85
+ @Test
86
+ public void checkDefaultValues()
87
+ {
88
+ ConfigSource config = Exec.newConfigSource()
89
+ .set("bucket", GCP_BUCKET)
90
+ .set("path_prefix", "my-prefix");
91
+
92
+ GcsFileInputPlugin.PluginTask task = config.loadConfig(PluginTask.class);
93
+ assertEquals("private_key", task.getAuthMethod().toString());
94
+ assertEquals("Embulk GCS input plugin", task.getApplicationName());
95
+ }
96
+
97
+ // p12_keyfile is null when auth_method is private_key
98
+ @Test(expected = ConfigException.class)
99
+ public void checkDefaultValuesP12keyNull()
100
+ {
101
+ ConfigSource config = Exec.newConfigSource()
102
+ .set("bucket", GCP_BUCKET)
103
+ .set("path_prefix", "my-prefix")
104
+ .set("auth_method", "private_key")
105
+ .set("service_account_email", GCP_EMAIL)
106
+ .set("p12_keyfile", null);
107
+
108
+ runner.transaction(config, new Control());
109
+ }
110
+
111
+ // both p12_keyfile and p12_keyfile_fullpath set
112
+ @Test(expected = ConfigException.class)
113
+ public void checkDefaultValuesConflictSetting()
114
+ {
115
+ ConfigSource config = Exec.newConfigSource()
116
+ .set("bucket", GCP_BUCKET)
117
+ .set("path_prefix", "my-prefix")
118
+ .set("auth_method", "private_key")
119
+ .set("service_account_email", GCP_EMAIL)
120
+ .set("p12_keyfile", GCP_P12_KEYFILE)
121
+ .set("p12_keyfile_fullpath", GCP_P12_KEYFILE);
122
+
123
+ runner.transaction(config, new Control());
124
+ }
125
+
126
+ // invalid p12keyfile when auth_method is private_key
127
+ @Test(expected = ConfigException.class)
128
+ public void checkDefaultValuesInvalidPrivateKey()
129
+ {
130
+ ConfigSource config = Exec.newConfigSource()
131
+ .set("bucket", GCP_BUCKET)
132
+ .set("path_prefix", "my-prefix")
133
+ .set("auth_method", "private_key")
134
+ .set("service_account_email", GCP_EMAIL)
135
+ .set("p12_keyfile", "invalid-key.p12");
136
+
137
+ runner.transaction(config, new Control());
138
+ }
139
+
140
+ // json_keyfile is null when auth_method is json_key
141
+ @Test(expected = ConfigException.class)
142
+ public void checkDefaultValuesJsonKeyfileNull()
143
+ {
144
+ ConfigSource config = Exec.newConfigSource()
145
+ .set("bucket", GCP_BUCKET)
146
+ .set("path_prefix", "my-prefix")
147
+ .set("auth_method", "json_key")
148
+ .set("service_account_email", GCP_EMAIL)
149
+ .set("json_keyfile", null);
150
+
151
+ runner.transaction(config, new Control());
152
+ }
153
+
154
+ @Test
155
+ public void testGcsClientCreateSuccessfully()
156
+ throws GeneralSecurityException, IOException, NoSuchFieldException
157
+ {
158
+ PluginTask task = config().loadConfig(PluginTask.class);
159
+ runner.transaction(config, new Control());
160
+ plugin.newGcsClient(task); // no errors happens
161
+ }
162
+
163
+ @Test(expected = ConfigException.class)
164
+ public void testGcsClientCreateThrowConfigException()
165
+ throws GeneralSecurityException, IOException, NoSuchFieldException
166
+ {
167
+ ConfigSource config = Exec.newConfigSource()
168
+ .set("bucket", "non-exists-bucket")
169
+ .set("path_prefix", "my-prefix")
170
+ .set("auth_method", "json_key")
171
+ .set("service_account_email", GCP_EMAIL)
172
+ .set("json_keyfile", GCP_JSON_KEYFILE);
173
+
174
+ PluginTask task = config().loadConfig(PluginTask.class);
175
+ runner.transaction(config, new Control());
176
+ plugin.newGcsClient(task);
177
+ }
178
+
179
+ @Test
180
+ public void testResume()
181
+ {
182
+ PluginTask task = config.loadConfig(PluginTask.class);
183
+ task.setFiles(Arrays.asList(new String[]{"in/aa/a"}));
184
+ ConfigDiff configDiff = plugin.resume(task.dump(), 0, new FileInputPlugin.Control()
185
+ {
186
+ @Override
187
+ public List<TaskReport> run(TaskSource taskSource, int taskCount)
188
+ {
189
+ return emptyTaskReports(taskCount);
190
+ }
191
+ });
192
+ assertEquals("in/aa/a", configDiff.get(String.class, "last_path"));
193
+ }
194
+
195
+ @Test
196
+ public void testCleanup()
197
+ {
198
+ PluginTask task = config.loadConfig(PluginTask.class);
199
+ plugin.cleanup(task.dump(), 0, Lists.<TaskReport>newArrayList()); // no errors happens
200
+ }
201
+
202
+ @Test
203
+ public void testListFilesByPrefix()
204
+ {
205
+ List<String> expected = Arrays.asList(
206
+ GCP_BUCKET_DIRECTORY + "sample_01.csv",
207
+ GCP_BUCKET_DIRECTORY + "sample_02.csv"
208
+ );
209
+
210
+ PluginTask task = config.loadConfig(PluginTask.class);
211
+ ConfigDiff configDiff = plugin.transaction(config, new FileInputPlugin.Control() {
212
+ @Override
213
+ public List<TaskReport> run(TaskSource taskSource, int taskCount) {
214
+ assertEquals(2, taskCount);
215
+ return emptyTaskReports(taskCount);
216
+ }
217
+ });
218
+
219
+ Storage client = plugin.newGcsClient(task);
220
+ List<String> actual = plugin.listGcsFilesByPrefix(client, GCP_BUCKET, GCP_PATH_PREFIX, Optional.<String>absent());
221
+ assertEquals(expected, actual);
222
+
223
+ assertEquals(GCP_BUCKET_DIRECTORY + "sample_02.csv", configDiff.get(String.class, "last_path"));
224
+ }
225
+
226
+ @Test
227
+ public void testListFilesByPrefixNonExistsBucket()
228
+ {
229
+ PluginTask task = config.loadConfig(PluginTask.class);
230
+ runner.transaction(config, new Control());
231
+ Storage client = plugin.newGcsClient(task);
232
+ plugin.listGcsFilesByPrefix(client, "non-exists-bucket", "prefix", Optional.<String>absent()); // no errors happens
233
+ }
234
+
235
+ @Test
236
+ public void testGcsFileInputByOpen() throws IOException
237
+ {
238
+ ConfigSource config = Exec.newConfigSource()
239
+ .set("bucket", GCP_BUCKET)
240
+ .set("path_prefix", GCP_PATH_PREFIX)
241
+ .set("auth_method", "json_key")
242
+ .set("service_account_email", GCP_EMAIL)
243
+ .set("json_keyfile", GCP_JSON_KEYFILE)
244
+ .set("parser", parserConfig(schemaConfig()));
245
+
246
+ PluginTask task = config.loadConfig(PluginTask.class);
247
+ runner.transaction(config, new Control());
248
+ task.setFiles(plugin.listFiles(task));
249
+
250
+ assertRecords(config, output);
251
+ }
252
+
253
+ public ConfigSource config()
254
+ {
255
+ return Exec.newConfigSource()
256
+ .set("bucket", GCP_BUCKET)
257
+ .set("path_prefix", GCP_PATH_PREFIX)
258
+ .set("auth_method", "private_key")
259
+ .set("service_account_email", GCP_EMAIL)
260
+ .set("p12_keyfile", GCP_P12_KEYFILE)
261
+ .set("json_keyfile", GCP_JSON_KEYFILE)
262
+ .set("application_name", GCP_APPLICATION_NAME)
263
+ .set("parser", parserConfig(schemaConfig()));
264
+ }
265
+
266
+ static List<TaskReport> emptyTaskReports(int taskCount)
267
+ {
268
+ ImmutableList.Builder<TaskReport> reports = new ImmutableList.Builder<>();
269
+ for (int i = 0; i < taskCount; i++) {
270
+ reports.add(Exec.newTaskReport());
271
+ }
272
+ return reports.build();
273
+ }
274
+
275
+ private class Control
276
+ implements InputPlugin.Control
277
+ {
278
+ @Override
279
+ public List<TaskReport> run(TaskSource taskSource, Schema schema, int taskCount)
280
+ {
281
+ List<TaskReport> reports = new ArrayList<>();
282
+ for (int i = 0; i < taskCount; i++) {
283
+ reports.add(runner.run(taskSource, schema, i, output));
284
+ }
285
+ return reports;
286
+ }
287
+ }
288
+
289
+ private ImmutableMap<String, Object> parserConfig(ImmutableList<Object> schemaConfig)
290
+ {
291
+ ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
292
+ builder.put("type", "csv");
293
+ builder.put("newline", "CRLF");
294
+ builder.put("delimiter", ",");
295
+ builder.put("quote", "\"");
296
+ builder.put("escape", "\"");
297
+ builder.put("trim_if_not_quoted", false);
298
+ builder.put("skip_header_lines", 1);
299
+ builder.put("allow_extra_columns", false);
300
+ builder.put("allow_optional_columns", false);
301
+ builder.put("columns", schemaConfig);
302
+ return builder.build();
303
+ }
304
+
305
+ private ImmutableList<Object> schemaConfig()
306
+ {
307
+ ImmutableList.Builder<Object> builder = new ImmutableList.Builder<>();
308
+ builder.add(ImmutableMap.of("name", "id", "type", "long"));
309
+ builder.add(ImmutableMap.of("name", "account", "type", "long"));
310
+ builder.add(ImmutableMap.of("name", "time", "type", "timestamp", "format", "%Y-%m-%d %H:%M:%S"));
311
+ builder.add(ImmutableMap.of("name", "purchase", "type", "timestamp", "format", "%Y%m%d"));
312
+ builder.add(ImmutableMap.of("name", "comment", "type", "string"));
313
+ return builder.build();
314
+ }
315
+
316
+ private void assertRecords(ConfigSource config, MockPageOutput output)
317
+ {
318
+ List<Object[]> records = getRecords(config, output);
319
+ assertEquals(8, records.size());
320
+ {
321
+ Object[] record = records.get(0);
322
+ assertEquals(1L, record[0]);
323
+ assertEquals(32864L, record[1]);
324
+ assertEquals("2015-01-27 19:23:49 UTC", record[2].toString());
325
+ assertEquals("2015-01-27 00:00:00 UTC", record[3].toString());
326
+ assertEquals("embulk", record[4]);
327
+ }
328
+
329
+ {
330
+ Object[] record = records.get(1);
331
+ assertEquals(2L, record[0]);
332
+ assertEquals(14824L, record[1]);
333
+ assertEquals("2015-01-27 19:01:23 UTC", record[2].toString());
334
+ assertEquals("2015-01-27 00:00:00 UTC", record[3].toString());
335
+ assertEquals("embulk jruby", record[4]);
336
+ }
337
+ }
338
+
339
+ private List<Object[]> getRecords(ConfigSource config, MockPageOutput output)
340
+ {
341
+ Schema schema = config.getNested("parser").loadConfig(CsvParserPlugin.PluginTask.class).getSchemaConfig().toSchema();
342
+ return Pages.toObjects(schema, output.pages);
343
+ }
6
344
 
7
- // @todo Write unit test.
8
- public class TestGcsFileInputPlugin {
345
+ private static String getDirectory(String dir)
346
+ {
347
+ if (dir != null && !dir.endsWith("/")) {
348
+ dir = dir + "/";
349
+ }
350
+ if (dir.startsWith("/")) {
351
+ dir = dir.replaceFirst("/", "");
352
+ }
353
+ return dir;
354
+ }
9
355
  }
@@ -0,0 +1,5 @@
1
+ id,account,time,purchase,comment
2
+ 1,32864,2015-01-27 19:23:49,20150127,embulk
3
+ 2,14824,2015-01-27 19:01:23,20150127,embulk jruby
4
+ 3,27559,2015-01-28 02:20:02,20150128,"Embulk ""csv"" parser plugin"
5
+ 4,11270,2015-01-29 11:54:36,20150129,NULL
@@ -0,0 +1,5 @@
1
+ id,account,time,purchase,comment
2
+ 1,32864,2015-01-27 19:23:49,20150127,embulk
3
+ 2,14824,2015-01-27 19:01:23,20150127,embulk jruby
4
+ 3,27559,2015-01-28 02:20:02,20150128,"Embulk ""csv"" parser plugin"
5
+ 4,11270,2015-01-29 11:54:36,20150129,NULL
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-input-gcs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Satoshi Akama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-06 00:00:00.000000000 Z
11
+ date: 2015-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -57,10 +57,13 @@ files:
57
57
  - settings.gradle
58
58
  - src/main/java/org/embulk/input/gcs/GcsAuthentication.java
59
59
  - src/main/java/org/embulk/input/gcs/GcsFileInputPlugin.java
60
+ - src/test/java/org/embulk/input/gcs/TestGcsAuthentication.java
60
61
  - src/test/java/org/embulk/input/gcs/TestGcsFileInputPlugin.java
62
+ - src/test/resources/sample_01.csv
63
+ - src/test/resources/sample_02.csv
61
64
  - classpath/commons-codec-1.3.jar
62
65
  - classpath/commons-logging-1.1.1.jar
63
- - classpath/embulk-input-gcs-0.1.7.jar
66
+ - classpath/embulk-input-gcs-0.1.8.jar
64
67
  - classpath/google-api-client-1.19.1.jar
65
68
  - classpath/google-api-services-storage-v1-rev27-1.19.1.jar
66
69
  - classpath/google-http-client-1.19.0.jar
Binary file