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
@@ -0,0 +1,145 @@
|
|
1
|
+
package org.embulk.input.gcs;
|
2
|
+
|
3
|
+
import com.google.cloud.ReadChannel;
|
4
|
+
import com.google.cloud.RestorableState;
|
5
|
+
import com.google.cloud.storage.Blob;
|
6
|
+
import com.google.cloud.storage.Storage;
|
7
|
+
import com.google.common.base.Charsets;
|
8
|
+
import com.google.common.io.Files;
|
9
|
+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
10
|
+
import org.embulk.EmbulkTestRuntime;
|
11
|
+
import org.embulk.spi.util.ResumableInputStream;
|
12
|
+
import org.junit.Rule;
|
13
|
+
import org.junit.Test;
|
14
|
+
import org.mockito.Mockito;
|
15
|
+
|
16
|
+
import java.io.ByteArrayOutputStream;
|
17
|
+
import java.io.File;
|
18
|
+
import java.io.IOException;
|
19
|
+
import java.nio.ByteBuffer;
|
20
|
+
import java.nio.channels.FileChannel;
|
21
|
+
import java.nio.file.Paths;
|
22
|
+
|
23
|
+
import static org.junit.Assert.assertEquals;
|
24
|
+
import static org.junit.Assert.fail;
|
25
|
+
import static org.mockito.ArgumentMatchers.any;
|
26
|
+
import static org.mockito.ArgumentMatchers.eq;
|
27
|
+
|
28
|
+
public class TestInputStreamReopener
|
29
|
+
{
|
30
|
+
private static class MockReadChannel implements ReadChannel
|
31
|
+
{
|
32
|
+
private FileChannel ch;
|
33
|
+
|
34
|
+
MockReadChannel(FileChannel ch)
|
35
|
+
{
|
36
|
+
this.ch = ch;
|
37
|
+
}
|
38
|
+
|
39
|
+
@Override
|
40
|
+
public boolean isOpen()
|
41
|
+
{
|
42
|
+
return this.ch.isOpen();
|
43
|
+
}
|
44
|
+
|
45
|
+
@Override
|
46
|
+
public void close()
|
47
|
+
{
|
48
|
+
try {
|
49
|
+
this.ch.close();
|
50
|
+
}
|
51
|
+
catch (IOException ignored) {
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
@Override
|
56
|
+
public void seek(long position) throws IOException
|
57
|
+
{
|
58
|
+
this.ch.position(position);
|
59
|
+
}
|
60
|
+
|
61
|
+
@Override
|
62
|
+
public void setChunkSize(int chunkSize)
|
63
|
+
{
|
64
|
+
// no-op
|
65
|
+
}
|
66
|
+
|
67
|
+
@Override
|
68
|
+
public RestorableState<ReadChannel> capture()
|
69
|
+
{
|
70
|
+
return null;
|
71
|
+
}
|
72
|
+
|
73
|
+
@Override
|
74
|
+
public int read(ByteBuffer dst) throws IOException
|
75
|
+
{
|
76
|
+
return this.ch.read(dst);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
private static final String SAMPLE_PATH = TestInputStreamReopener.class.getResource("/sample_01.csv").getPath();
|
81
|
+
|
82
|
+
@SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
|
83
|
+
@Rule
|
84
|
+
public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
|
85
|
+
|
86
|
+
@Test
|
87
|
+
public void testResume()
|
88
|
+
{
|
89
|
+
final String bucket = "any_bucket";
|
90
|
+
final String key = "any_file";
|
91
|
+
|
92
|
+
final Storage client = mockStorage();
|
93
|
+
|
94
|
+
final SingleFileProvider.InputStreamReopener reopener = new SingleFileProvider.InputStreamReopener(client, bucket, key);
|
95
|
+
final byte[] buf = new byte[200];
|
96
|
+
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
97
|
+
try (final ResumableInputStream ris = new ResumableInputStream(reopener)) {
|
98
|
+
int len;
|
99
|
+
while ((len = ris.read(buf)) != -1) {
|
100
|
+
out.write(buf, 0, len);
|
101
|
+
}
|
102
|
+
// read from resumable input stream
|
103
|
+
String content = out.toString("UTF-8");
|
104
|
+
// assert content
|
105
|
+
assertString(content);
|
106
|
+
}
|
107
|
+
catch (IOException e) {
|
108
|
+
e.printStackTrace();
|
109
|
+
fail("Should not throw");
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
private Storage mockStorage()
|
114
|
+
{
|
115
|
+
Blob blob = Mockito.mock(Blob.class);
|
116
|
+
// mock Storage to return ReadChannel
|
117
|
+
Storage client = Mockito.mock(Storage.class);
|
118
|
+
Mockito.doReturn(blob).when(client).get(eq("any_bucket"), eq("any_file"));
|
119
|
+
// to return new instance every time (can't re-use channel, because it'll be closed)
|
120
|
+
Mockito.doAnswer(invocation -> new MockReadChannel(mockChannel())).when(blob).reader();
|
121
|
+
return client;
|
122
|
+
}
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Return a mock FileChannel, with simulated error during reads
|
126
|
+
*
|
127
|
+
* @return
|
128
|
+
* @throws IOException
|
129
|
+
*/
|
130
|
+
private static FileChannel mockChannel() throws IOException
|
131
|
+
{
|
132
|
+
FileChannel ch = Mockito.spy(FileChannel.open(Paths.get(SAMPLE_PATH)));
|
133
|
+
// success -> error -> success -> error...
|
134
|
+
Mockito.doCallRealMethod()
|
135
|
+
.doThrow(new IOException("Fake IOException, going to resume"))
|
136
|
+
.when(ch).read(any(ByteBuffer.class));
|
137
|
+
return ch;
|
138
|
+
}
|
139
|
+
|
140
|
+
private static void assertString(final String actual) throws IOException
|
141
|
+
{
|
142
|
+
final String expected = Files.asCharSource(new File(SAMPLE_PATH), Charsets.UTF_8).read();
|
143
|
+
assertEquals(expected, actual);
|
144
|
+
}
|
145
|
+
}
|
@@ -0,0 +1,164 @@
|
|
1
|
+
package org.embulk.input.gcs;
|
2
|
+
|
3
|
+
import com.google.api.client.auth.oauth2.TokenResponseException;
|
4
|
+
import com.google.api.client.googleapis.json.GoogleJsonError;
|
5
|
+
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
6
|
+
import com.google.api.client.http.HttpHeaders;
|
7
|
+
import com.google.api.client.http.HttpRequest;
|
8
|
+
import com.google.api.client.http.HttpTransport;
|
9
|
+
import com.google.api.client.http.LowLevelHttpRequest;
|
10
|
+
import com.google.api.client.http.LowLevelHttpResponse;
|
11
|
+
import com.google.api.client.json.Json;
|
12
|
+
import com.google.api.client.json.jackson2.JacksonFactory;
|
13
|
+
import com.google.api.client.testing.http.HttpTesting;
|
14
|
+
import com.google.api.client.testing.http.MockHttpTransport;
|
15
|
+
import com.google.api.client.testing.http.MockLowLevelHttpRequest;
|
16
|
+
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
|
17
|
+
import com.google.cloud.storage.StorageException;
|
18
|
+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
19
|
+
import org.embulk.EmbulkTestRuntime;
|
20
|
+
import org.embulk.spi.Exec;
|
21
|
+
import org.junit.Before;
|
22
|
+
import org.junit.Rule;
|
23
|
+
import org.junit.Test;
|
24
|
+
import org.mockito.Mockito;
|
25
|
+
|
26
|
+
import java.io.IOException;
|
27
|
+
|
28
|
+
import static org.embulk.input.gcs.RetryUtils.withRetry;
|
29
|
+
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
30
|
+
import static org.junit.Assert.assertEquals;
|
31
|
+
import static org.junit.Assert.assertFalse;
|
32
|
+
import static org.junit.Assert.assertNull;
|
33
|
+
import static org.junit.Assert.assertThat;
|
34
|
+
import static org.junit.Assert.assertTrue;
|
35
|
+
|
36
|
+
public class TestRetryUtils
|
37
|
+
{
|
38
|
+
@SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
|
39
|
+
@Rule
|
40
|
+
public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
|
41
|
+
|
42
|
+
private RetryUtils.DefaultRetryable<Object> mock;
|
43
|
+
|
44
|
+
@Before
|
45
|
+
public void setUp()
|
46
|
+
{
|
47
|
+
mock = new RetryUtils.DefaultRetryable<Object>()
|
48
|
+
{
|
49
|
+
@Override
|
50
|
+
public Object call()
|
51
|
+
{
|
52
|
+
return null;
|
53
|
+
}
|
54
|
+
};
|
55
|
+
}
|
56
|
+
|
57
|
+
@Test
|
58
|
+
public void testRetryable() throws IOException
|
59
|
+
{
|
60
|
+
// verify that #isRetryable() returns false for below cases:
|
61
|
+
// - GoogleJsonResponseException && details.code == 4xx
|
62
|
+
assertFalse(mock.isRetryableException(fakeJsonException(400, "fake_400_ex", null)));
|
63
|
+
// - TokenResponseException && statusCode == 4xx
|
64
|
+
assertFalse(mock.isRetryableException(fakeTokenException(400, "{}")));
|
65
|
+
assertFalse(mock.isRetryableException(fakeTokenException(401, "{\"foo\":\"bar\"}")));
|
66
|
+
assertFalse(mock.isRetryableException(fakeTokenException(403, "{ \"error_description\": \"Invalid...\"}")));
|
67
|
+
// return true
|
68
|
+
// - GoogleJsonResponseException && details.code = 5xx
|
69
|
+
assertTrue(mock.isRetryableException(fakeJsonException(500, "fake_500_ex", null)));
|
70
|
+
// - GoogleJsonResponseException && details == null && content != null
|
71
|
+
assertTrue(mock.isRetryableException(fakeJsonExceptionWithoutDetails(400, "fake_400_ex", "this content will make it retry-able")));
|
72
|
+
// - TokenResponseException && statusCode = 5xx
|
73
|
+
assertTrue(mock.isRetryableException(fakeTokenException(500, "{}")));
|
74
|
+
// - TokenResponseException && details.errorDescription contains 'Invalid JWT'
|
75
|
+
assertTrue(mock.isRetryableException(fakeTokenException(403, "{ \"error_description\": \"Invalid JWT...\"}")));
|
76
|
+
}
|
77
|
+
|
78
|
+
@Test
|
79
|
+
public void testWithRetry() throws Exception
|
80
|
+
{
|
81
|
+
mock = Mockito.spy(mock);
|
82
|
+
Exception ex = new StorageException(403, "Fake Exception");
|
83
|
+
Mockito.doThrow(ex).doThrow(ex).doReturn(null).when(mock).call();
|
84
|
+
|
85
|
+
Object result = withRetry(params(), mock);
|
86
|
+
assertNull(result);
|
87
|
+
Mockito.verify(mock, Mockito.times(3)).call();
|
88
|
+
}
|
89
|
+
|
90
|
+
@Test
|
91
|
+
public void testWithRetryGiveUp()
|
92
|
+
{
|
93
|
+
final String expectMsg = "Will retry and give up";
|
94
|
+
mock = new RetryUtils.DefaultRetryable<Object>()
|
95
|
+
{
|
96
|
+
@Override
|
97
|
+
public Object call()
|
98
|
+
{
|
99
|
+
throw new IllegalStateException(expectMsg);
|
100
|
+
}
|
101
|
+
};
|
102
|
+
try {
|
103
|
+
withRetry(params(), mock);
|
104
|
+
}
|
105
|
+
catch (RuntimeException e) {
|
106
|
+
// root cause -> RetryGiveUpException -> RuntimeException
|
107
|
+
Throwable rootCause = e.getCause().getCause();
|
108
|
+
assertEquals(expectMsg, rootCause.getMessage());
|
109
|
+
assertThat(rootCause, instanceOf(IllegalStateException.class));
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
private static RetryUtils.Task params()
|
114
|
+
{
|
115
|
+
return Exec.newConfigSource().set("initial_retry_interval_millis", 1).loadConfig(RetryUtils.Task.class);
|
116
|
+
}
|
117
|
+
|
118
|
+
private static GoogleJsonResponseException fakeJsonException(final int code, final String message, final String content)
|
119
|
+
{
|
120
|
+
GoogleJsonResponseException.Builder builder = new GoogleJsonResponseException.Builder(code, message, new HttpHeaders());
|
121
|
+
builder.setContent(content);
|
122
|
+
return new GoogleJsonResponseException(builder, fakeJsonError(code, message));
|
123
|
+
}
|
124
|
+
|
125
|
+
private static GoogleJsonResponseException fakeJsonExceptionWithoutDetails(final int code, final String message, final String content)
|
126
|
+
{
|
127
|
+
GoogleJsonResponseException.Builder builder = new GoogleJsonResponseException.Builder(code, message, new HttpHeaders());
|
128
|
+
builder.setContent(content);
|
129
|
+
return new GoogleJsonResponseException(builder, null);
|
130
|
+
}
|
131
|
+
|
132
|
+
private static GoogleJsonError fakeJsonError(final int code, final String message)
|
133
|
+
{
|
134
|
+
GoogleJsonError error = new GoogleJsonError();
|
135
|
+
error.setCode(code);
|
136
|
+
error.setMessage(message);
|
137
|
+
return error;
|
138
|
+
}
|
139
|
+
|
140
|
+
private static TokenResponseException fakeTokenException(final int code, final String content) throws IOException
|
141
|
+
{
|
142
|
+
HttpTransport transport = new MockHttpTransport() {
|
143
|
+
@Override
|
144
|
+
public LowLevelHttpRequest buildRequest(String method, String url)
|
145
|
+
{
|
146
|
+
return new MockLowLevelHttpRequest() {
|
147
|
+
@Override
|
148
|
+
public LowLevelHttpResponse execute()
|
149
|
+
{
|
150
|
+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
|
151
|
+
response.addHeader("custom_header", "value");
|
152
|
+
response.setStatusCode(code);
|
153
|
+
response.setContentType(Json.MEDIA_TYPE);
|
154
|
+
response.setContent(content);
|
155
|
+
return response;
|
156
|
+
}
|
157
|
+
};
|
158
|
+
}
|
159
|
+
};
|
160
|
+
HttpRequest request = transport.createRequestFactory().buildGetRequest(HttpTesting.SIMPLE_GENERIC_URL);
|
161
|
+
request.setThrowExceptionOnExecuteError(false);
|
162
|
+
return TokenResponseException.from(JacksonFactory.getDefaultInstance(), request.execute());
|
163
|
+
}
|
164
|
+
}
|
Binary file
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-gcs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Satoshi Akama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
|
-
- - ~>
|
16
|
+
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
18
|
version: '1.0'
|
19
19
|
name: bundler
|
@@ -21,13 +21,13 @@ dependencies:
|
|
21
21
|
type: :development
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
|
-
- -
|
30
|
+
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '10.0'
|
33
33
|
name: rake
|
@@ -35,21 +35,56 @@ dependencies:
|
|
35
35
|
type: :development
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
-
description: Reads files stored on Google Cloud Storage (Standard, Durable Reduced
|
41
|
+
description: Reads files stored on Google Cloud Storage (Standard, Durable Reduced
|
42
|
+
Availability or Nearline)
|
42
43
|
email:
|
43
44
|
- satoshiakama@gmail.com
|
44
45
|
executables: []
|
45
46
|
extensions: []
|
46
47
|
extra_rdoc_files: []
|
47
48
|
files:
|
48
|
-
- .gitignore
|
49
|
-
- .travis.yml
|
49
|
+
- ".gitignore"
|
50
|
+
- ".travis.yml"
|
50
51
|
- CHANGELOG.md
|
51
52
|
- README.md
|
52
53
|
- build.gradle
|
54
|
+
- classpath/animal-sniffer-annotations-1.14.jar
|
55
|
+
- classpath/api-common-1.7.0.jar
|
56
|
+
- classpath/checker-compat-qual-2.5.2.jar
|
57
|
+
- classpath/commons-codec-1.10.jar
|
58
|
+
- classpath/commons-logging-1.2.jar
|
59
|
+
- classpath/embulk-input-gcs-0.3.1-shadow.jar
|
60
|
+
- classpath/error_prone_annotations-2.1.3.jar
|
61
|
+
- classpath/gax-1.35.1.jar
|
62
|
+
- classpath/gax-httpjson-0.52.1.jar
|
63
|
+
- classpath/google-api-client-1.27.0.jar
|
64
|
+
- classpath/google-api-services-storage-v1-rev20181013-1.27.0.jar
|
65
|
+
- classpath/google-auth-library-credentials-0.12.0.jar
|
66
|
+
- classpath/google-auth-library-oauth2-http-0.12.0.jar
|
67
|
+
- classpath/google-cloud-core-1.56.0.jar
|
68
|
+
- classpath/google-cloud-core-http-1.56.0.jar
|
69
|
+
- classpath/google-http-client-1.27.0.jar
|
70
|
+
- classpath/google-http-client-appengine-1.27.0.jar
|
71
|
+
- classpath/google-http-client-jackson2-1.27.0.jar
|
72
|
+
- classpath/google-oauth-client-1.27.0.jar
|
73
|
+
- classpath/grpc-context-1.12.0.jar
|
74
|
+
- classpath/gson-2.7.jar
|
75
|
+
- classpath/httpclient-4.5.5.jar
|
76
|
+
- classpath/httpcore-4.4.9.jar
|
77
|
+
- classpath/j2objc-annotations-1.1.jar
|
78
|
+
- classpath/jackson-core-2.9.6.jar
|
79
|
+
- classpath/javax.annotation-api-1.2.jar
|
80
|
+
- classpath/jsr305-3.0.2.jar
|
81
|
+
- classpath/opencensus-api-0.15.0.jar
|
82
|
+
- classpath/opencensus-contrib-http-util-0.15.0.jar
|
83
|
+
- classpath/proto-google-common-protos-1.12.0.jar
|
84
|
+
- classpath/proto-google-iam-v1-0.12.0.jar
|
85
|
+
- classpath/protobuf-java-3.6.1.jar
|
86
|
+
- classpath/protobuf-java-util-3.6.1.jar
|
87
|
+
- classpath/threetenbp-1.3.3.jar
|
53
88
|
- config/checkstyle/checkstyle.xml
|
54
89
|
- config/checkstyle/default.xml
|
55
90
|
- gradle/wrapper/gradle-wrapper.jar
|
@@ -57,31 +92,21 @@ files:
|
|
57
92
|
- gradlew
|
58
93
|
- gradlew.bat
|
59
94
|
- lib/embulk/input/gcs.rb
|
60
|
-
- secretkeys.tar
|
61
|
-
- secretkeys.tar.enc
|
62
95
|
- settings.gradle
|
96
|
+
- src/main/java/org/embulk/input/gcs/AuthUtils.java
|
63
97
|
- src/main/java/org/embulk/input/gcs/FileList.java
|
64
|
-
- src/main/java/org/embulk/input/gcs/GcsAuthentication.java
|
65
98
|
- src/main/java/org/embulk/input/gcs/GcsFileInput.java
|
66
99
|
- src/main/java/org/embulk/input/gcs/GcsFileInputPlugin.java
|
67
100
|
- src/main/java/org/embulk/input/gcs/PluginTask.java
|
101
|
+
- src/main/java/org/embulk/input/gcs/RetryUtils.java
|
68
102
|
- src/main/java/org/embulk/input/gcs/SingleFileProvider.java
|
69
|
-
- src/test/java/org/embulk/input/gcs/
|
103
|
+
- src/test/java/org/embulk/input/gcs/TestAuthUtils.java
|
70
104
|
- src/test/java/org/embulk/input/gcs/TestGcsFileInputPlugin.java
|
105
|
+
- src/test/java/org/embulk/input/gcs/TestInputStreamReopener.java
|
106
|
+
- src/test/java/org/embulk/input/gcs/TestRetryUtils.java
|
71
107
|
- src/test/resources/sample_01.csv
|
72
108
|
- src/test/resources/sample_02.csv
|
73
|
-
- src/test/resources/
|
74
|
-
- classpath/google-api-client-1.21.0.jar
|
75
|
-
- classpath/httpclient-4.0.1.jar
|
76
|
-
- classpath/jsr305-1.3.9.jar
|
77
|
-
- classpath/commons-logging-1.1.1.jar
|
78
|
-
- classpath/google-api-services-storage-v1-rev59-1.21.0.jar
|
79
|
-
- classpath/google-http-client-1.21.0.jar
|
80
|
-
- classpath/google-oauth-client-1.21.0.jar
|
81
|
-
- classpath/commons-codec-1.3.jar
|
82
|
-
- classpath/google-http-client-jackson2-1.21.0.jar
|
83
|
-
- classpath/httpcore-4.0.1.jar
|
84
|
-
- classpath/embulk-input-gcs-0.3.0.jar
|
109
|
+
- src/test/resources/secrets.tar.enc
|
85
110
|
homepage: https://github.com/embulk/embulk-input-gcs
|
86
111
|
licenses:
|
87
112
|
- Apache-2.0
|
@@ -92,17 +117,17 @@ require_paths:
|
|
92
117
|
- lib
|
93
118
|
required_ruby_version: !ruby/object:Gem::Requirement
|
94
119
|
requirements:
|
95
|
-
- -
|
120
|
+
- - ">="
|
96
121
|
- !ruby/object:Gem::Version
|
97
122
|
version: '0'
|
98
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
124
|
requirements:
|
100
|
-
- -
|
125
|
+
- - ">="
|
101
126
|
- !ruby/object:Gem::Version
|
102
127
|
version: '0'
|
103
128
|
requirements: []
|
104
129
|
rubyforge_project:
|
105
|
-
rubygems_version: 2.
|
130
|
+
rubygems_version: 2.6.13
|
106
131
|
signing_key:
|
107
132
|
specification_version: 4
|
108
133
|
summary: Google Cloud Storage input plugin for Embulk
|