embulk-output-gcs 0.1.1 → 0.2.0

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: 7cc14163dab8e5bcae3c1b71d6a6e51493f460f3
4
- data.tar.gz: 0ed896983dd82d5753d5beb57b9d10642c2521f7
3
+ metadata.gz: 94fccd956be721058fbf74ffd57017d05caf8e5b
4
+ data.tar.gz: e7e35ef7704225a633d47babdd21c91edd6ad272
5
5
  SHA512:
6
- metadata.gz: 0d946fc00317318cc84605f589c6c9c5b5c6d8525b799f3a69e87d5f14d6c2060084c2e3a528a6a84dec8210bfe3bccf3a0ab9a639c1c1051f0ab83c30db34dd
7
- data.tar.gz: f78b3ea4c04e04364787bfe987b4d5542e97ba3f41ed0c873a0142dea5b7dcf0bb5d9fe9b4c8db4e0ed649868517bc4e36ce88142b9a6e1b000f3e85e38f6491
6
+ metadata.gz: 2b2325cf0230d16f57fb7a247a9237428fd2d4527cd6848367a5989e3d8bc9a9da7f282b3a81ec97ad2425da9bb70cbd0a26465fcc1dd747ce3e804908cd48ad
7
+ data.tar.gz: ceb4828ba593c2e2ab8cf043bce26b4509867489cf3b7eac96fd00f1ef10b5ffe8895587a1844d7b01671ea0373cd30b82d39a94da2caf8183cdee206dcdd4e7
data/README.md CHANGED
@@ -15,6 +15,7 @@ Google Cloud Storage output plugin for [Embulk](https://github.com/embulk/embulk
15
15
  - **path_prefix**: Prefix of output keys (string, required)
16
16
  - **file_ext**: Extention of output file (string, required)
17
17
  - **content_type**: content type of output file (string, optional, default value is "application/octet-stream")
18
+ - **auth_method**: Authentication method `private_key` or `compute_engine` (string, optional, default value is "private_key")
18
19
  - **service_account_email**: Google Cloud Platform service account email (string, required)
19
20
  - **p12_keyfile_path**: Private key file fullpath of Google Cloud Platform service account (string, required)
20
21
  - **application_name**: Application name, anything you like (string, optional, default value is "embulk-output-gcs")
@@ -27,6 +28,7 @@ out:
27
28
  bucket: your-gcs-bucket-name
28
29
  path_prefix: logs/out
29
30
  file_ext: .csv
31
+ auth_method: `private_key` #default
30
32
  service_account_email: 'XYZ@developer.gserviceaccount.com'
31
33
  p12_keyfile_path: '/path/to/private/key.p12'
32
34
  formatter:
@@ -34,6 +36,29 @@ out:
34
36
  encoding: UTF-8
35
37
  ```
36
38
 
39
+ ## Authentication
40
+
41
+ There are two methods supported to fetch access token for the service account.
42
+
43
+ 1. Public-Private key pair
44
+ 2. Pre-defined access token (Compute Engine only)
45
+
46
+ The examples above use the first one. You first need to create a service account (client ID),
47
+ download its private key and deploy the key with embulk.
48
+
49
+ On the other hand, you don't need to explicitly create a service account for embulk when you
50
+ run embulk in Google Compute Engine. In this second authentication method, you need to
51
+ add the API scope "https://www.googleapis.com/auth/devstorage.read_write" to the scope list of your
52
+ Compute Engine instance, then you can configure embulk like this.
53
+
54
+ [Setting the scope of service account access for instances](https://cloud.google.com/compute/docs/authentication)
55
+
56
+ ```yaml
57
+ out:
58
+ type: gcs
59
+ auth_method: compute_engine
60
+ ```
61
+
37
62
  ## Build
38
63
 
39
64
  ```
data/build.gradle CHANGED
@@ -15,11 +15,11 @@ configurations {
15
15
  sourceCompatibility = 1.7
16
16
  targetCompatibility = 1.7
17
17
 
18
- version = "0.1.1"
18
+ version = "0.2.0"
19
19
 
20
20
  dependencies {
21
- compile "org.embulk:embulk-core:0.5.1"
22
- provided "org.embulk:embulk-core:0.5.1"
21
+ compile "org.embulk:embulk-core:0.7.3"
22
+ provided "org.embulk:embulk-core:0.7.3"
23
23
 
24
24
  compile "com.google.http-client:google-http-client-jackson2:1.19.0"
25
25
  compile ("com.google.apis:google-api-services-storage:v1-rev28-1.19.1") {exclude module: "guava-jdk5"}
Binary file
@@ -1,6 +1,6 @@
1
- #Wed Feb 04 13:46:12 PST 2015
1
+ #Tue Aug 11 00:26:20 PDT 2015
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.2.1-bin.zip
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip
@@ -0,0 +1,96 @@
1
+ package org.embulk.output;
2
+
3
+ import java.io.File;
4
+ import java.io.IOException;
5
+
6
+ import com.google.api.client.http.apache.ApacheHttpTransport;
7
+ import com.google.api.services.storage.model.Objects;
8
+ import com.google.common.base.Optional;
9
+ import com.google.common.collect.ImmutableList;
10
+ import java.security.GeneralSecurityException;
11
+ import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
12
+ import com.google.api.client.googleapis.compute.ComputeCredential;
13
+ import com.google.api.client.http.HttpTransport;
14
+ import com.google.api.client.json.JsonFactory;
15
+ import com.google.api.client.json.jackson2.JacksonFactory;
16
+ import com.google.api.client.http.HttpRequestInitializer;
17
+ import com.google.api.client.googleapis.json.GoogleJsonResponseException;
18
+ import com.google.api.services.storage.Storage;
19
+ import com.google.api.services.storage.StorageScopes;
20
+ import org.embulk.spi.Exec;
21
+ import org.slf4j.Logger;
22
+
23
+ public class GcsAuthentication
24
+ {
25
+ private final Logger log = Exec.getLogger(GcsAuthentication.class);
26
+ private final Optional<String> serviceAccountEmail;
27
+ private final Optional<String> p12KeyFilePath;
28
+ private final String applicationName;
29
+ private final HttpTransport httpTransport;
30
+ private final JsonFactory jsonFactory;
31
+ private final HttpRequestInitializer credentials;
32
+
33
+ public GcsAuthentication(String authMethod, Optional<String> serviceAccountEmail, Optional<String> p12KeyFilePath, String applicationName)
34
+ throws IOException, GeneralSecurityException
35
+ {
36
+ this.serviceAccountEmail = serviceAccountEmail;
37
+ this.p12KeyFilePath = p12KeyFilePath;
38
+ this.applicationName = applicationName;
39
+
40
+ this.httpTransport = new ApacheHttpTransport.Builder().build();
41
+ this.jsonFactory = new JacksonFactory();
42
+
43
+ if (authMethod.equals("compute_engine")) {
44
+ this.credentials = getComputeCredential();
45
+ } else {
46
+ this.credentials = getServiceAccountCredential();
47
+ }
48
+ }
49
+
50
+ /**
51
+ * @see https://developers.google.com/accounts/docs/OAuth2ServiceAccount#authorizingrequests
52
+ */
53
+ private GoogleCredential getServiceAccountCredential() throws IOException, GeneralSecurityException
54
+ {
55
+ // @see https://cloud.google.com/compute/docs/api/how-tos/authorization
56
+ // @see https://developers.google.com/resources/api-libraries/documentation/storage/v1/java/latest/com/google/api/services/storage/STORAGE_SCOPE.html
57
+ // @see https://developers.google.com/resources/api-libraries/documentation/bigquery/v2/java/latest/com/google/api/services/bigquery/BigqueryScopes.html
58
+ return new GoogleCredential.Builder()
59
+ .setTransport(httpTransport)
60
+ .setJsonFactory(jsonFactory)
61
+ .setServiceAccountId(serviceAccountEmail.orNull())
62
+ .setServiceAccountScopes(
63
+ ImmutableList.of(
64
+ StorageScopes.DEVSTORAGE_READ_WRITE
65
+ )
66
+ )
67
+ .setServiceAccountPrivateKeyFromP12File(new File(p12KeyFilePath.orNull()))
68
+ .build();
69
+ }
70
+
71
+ /**
72
+ * @see http://developers.guge.io/accounts/docs/OAuth2ServiceAccount#creatinganaccount
73
+ * @see https://developers.google.com/accounts/docs/OAuth2
74
+ */
75
+ private ComputeCredential getComputeCredential() throws IOException
76
+ {
77
+ ComputeCredential credential = new ComputeCredential.Builder(httpTransport, jsonFactory)
78
+ .build();
79
+ credential.refreshToken();
80
+
81
+ return credential;
82
+ }
83
+
84
+ public Storage getGcsClient(String bucket) throws GoogleJsonResponseException, IOException
85
+ {
86
+ Storage client = new Storage.Builder(httpTransport, jsonFactory, credentials)
87
+ .setApplicationName(applicationName)
88
+ .build();
89
+
90
+ // For throw IOException when authentication is fail.
91
+ long maxResults = 1;
92
+ Objects objects = client.objects().list(bucket).setMaxResults(maxResults).execute();
93
+
94
+ return client;
95
+ }
96
+ }
@@ -1,22 +1,16 @@
1
1
  package org.embulk.output;
2
2
 
3
- import com.google.api.client.auth.oauth2.Credential;
4
- import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
5
- import com.google.api.client.http.HttpTransport;
6
3
  import com.google.api.client.http.InputStreamContent;
7
- import com.google.api.client.http.apache.ApacheHttpTransport;
8
- import com.google.api.client.json.JsonFactory;
9
- import com.google.api.client.json.jackson2.JacksonFactory;
10
4
  import com.google.api.services.storage.Storage;
11
- import com.google.api.services.storage.StorageScopes;
12
5
  import com.google.api.services.storage.model.StorageObject;
6
+ import com.google.common.base.Optional;
13
7
  import com.google.common.base.Throwables;
14
- import com.google.common.collect.ImmutableList;
15
- import org.embulk.config.CommitReport;
8
+ import org.embulk.config.TaskReport;
16
9
  import org.embulk.config.Config;
17
10
  import org.embulk.config.ConfigDefault;
18
11
  import org.embulk.config.ConfigDiff;
19
12
  import org.embulk.config.ConfigSource;
13
+ import org.embulk.config.ConfigException;
20
14
  import org.embulk.config.Task;
21
15
  import org.embulk.config.TaskSource;
22
16
  import org.embulk.spi.Buffer;
@@ -25,7 +19,6 @@ import org.embulk.spi.FileOutputPlugin;
25
19
  import org.embulk.spi.TransactionalFileOutput;
26
20
  import org.slf4j.Logger;
27
21
 
28
- import java.io.File;
29
22
  import java.io.IOException;
30
23
  import java.io.PipedInputStream;
31
24
  import java.io.PipedOutputStream;
@@ -40,35 +33,40 @@ import java.util.concurrent.Future;
40
33
 
41
34
  public class GcsOutputPlugin implements FileOutputPlugin {
42
35
  private static final Logger logger = Exec.getLogger(GcsOutputPlugin.class);
43
- private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
44
36
 
45
37
  public interface PluginTask extends Task {
46
38
  @Config("bucket")
47
- public String getBucket();
39
+ String getBucket();
48
40
 
49
41
  @Config("path_prefix")
50
- public String getPathPrefix();
42
+ String getPathPrefix();
51
43
 
52
44
  @Config("file_ext")
53
- public String getFileNameExtension();
45
+ String getFileNameExtension();
54
46
 
55
47
  @Config("sequence_format")
56
48
  @ConfigDefault("\".%03d.%02d\"")
57
- public String getSequenceFormat();
49
+ String getSequenceFormat();
58
50
 
59
51
  @Config("content_type")
60
52
  @ConfigDefault("\"application/octet-stream\"")
61
- public String getContentType();
53
+ String getContentType();
54
+
55
+ @Config("auth_method")
56
+ @ConfigDefault("\"private_key\"")
57
+ AuthMethod getAuthMethod();
62
58
 
63
59
  @Config("service_account_email")
64
- public String getServiceAccountEmail();
60
+ @ConfigDefault("null")
61
+ Optional<String> getServiceAccountEmail();
65
62
 
66
63
  @Config("p12_keyfile_path")
67
- public String getP12KeyfilePath();
64
+ @ConfigDefault("null")
65
+ Optional<String> getP12KeyfilePath();
68
66
 
69
67
  @Config("application_name")
70
68
  @ConfigDefault("\"embulk-output-gcs\"")
71
- public String getApplicationName();
69
+ String getApplicationName();
72
70
  }
73
71
 
74
72
  @Override
@@ -90,7 +88,7 @@ public class GcsOutputPlugin implements FileOutputPlugin {
90
88
  @Override
91
89
  public void cleanup(TaskSource taskSource,
92
90
  int taskCount,
93
- List<CommitReport> successCommitReports) {
91
+ List<TaskReport> successTaskReports) {
94
92
  }
95
93
 
96
94
  @Override
@@ -101,34 +99,15 @@ public class GcsOutputPlugin implements FileOutputPlugin {
101
99
  return new TransactionalGcsFileOutput(task, client, taskIndex);
102
100
  }
103
101
 
104
- private GoogleCredential createCredential(final PluginTask task, final HttpTransport httpTransport) {
102
+ private Storage createClient(final PluginTask task) {
103
+ Storage client = null;
105
104
  try {
106
- // @see https://developers.google.com/accounts/docs/OAuth2ServiceAccount#authorizingrequests
107
- // @see https://cloud.google.com/compute/docs/api/how-tos/authorization
108
- // @see https://developers.google.com/resources/api-libraries/documentation/storage/v1/java/latest/com/google/api/services/storage/STORAGE_SCOPE.html
109
- GoogleCredential cred = new GoogleCredential.Builder()
110
- .setTransport(httpTransport)
111
- .setJsonFactory(JSON_FACTORY)
112
- .setServiceAccountId(task.getServiceAccountEmail())
113
- .setServiceAccountScopes(ImmutableList.of(StorageScopes.DEVSTORAGE_READ_WRITE))
114
- .setServiceAccountPrivateKeyFromP12File(new File(task.getP12KeyfilePath()))
115
- .build();
116
- return cred;
117
- } catch (IOException ex) {
118
- logger.error(String.format("Could not load client secrets file %s", task.getP12KeyfilePath()));
119
- throw Throwables.propagate(ex);
120
- } catch (GeneralSecurityException ex) {
121
- logger.error("Google Authentication was failed");
122
- throw Throwables.propagate(ex);
105
+ GcsAuthentication auth = new GcsAuthentication(task.getAuthMethod().getString(), task.getServiceAccountEmail(), task.getP12KeyfilePath(), task.getApplicationName());
106
+ client = auth.getGcsClient(task.getBucket());
107
+ } catch (GeneralSecurityException | IOException ex) {
108
+ throw new ConfigException(ex);
123
109
  }
124
- }
125
110
 
126
- private Storage createClient(final PluginTask task) {
127
- HttpTransport httpTransport = new ApacheHttpTransport.Builder().build();
128
- Credential credential = createCredential(task, httpTransport);
129
- Storage client = new Storage.Builder(httpTransport, JSON_FACTORY, credential)
130
- .setApplicationName(task.getApplicationName())
131
- .build();
132
111
  return client;
133
112
  }
134
113
 
@@ -194,8 +173,8 @@ public class GcsOutputPlugin implements FileOutputPlugin {
194
173
  }
195
174
 
196
175
  @Override
197
- public CommitReport commit() {
198
- CommitReport report = Exec.newCommitReport();
176
+ public TaskReport commit() {
177
+ TaskReport report = Exec.newTaskReport();
199
178
  report.set("files", storageObjects);
200
179
  return report;
201
180
  }
@@ -250,4 +229,22 @@ public class GcsOutputPlugin implements FileOutputPlugin {
250
229
  }
251
230
  }
252
231
  }
232
+
233
+ public enum AuthMethod
234
+ {
235
+ private_key("private_key"),
236
+ compute_engine("compute_engine");
237
+
238
+ private final String string;
239
+
240
+ AuthMethod(String string)
241
+ {
242
+ this.string = string;
243
+ }
244
+
245
+ public String getString()
246
+ {
247
+ return string;
248
+ }
249
+ }
253
250
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-gcs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuyuki Honda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-15 00:00:00.000000000 Z
11
+ date: 2015-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -59,11 +59,12 @@ files:
59
59
  - gradlew
60
60
  - gradlew.bat
61
61
  - lib/embulk/output/gcs.rb
62
+ - src/main/java/org/embulk/output/GcsAuthentication.java
62
63
  - src/main/java/org/embulk/output/GcsOutputPlugin.java
63
64
  - src/test/java/org/embulk/output/TestGcsOutputPlugin.java
64
65
  - classpath/commons-codec-1.3.jar
65
66
  - classpath/commons-logging-1.1.1.jar
66
- - classpath/embulk-output-gcs-0.1.1.jar
67
+ - classpath/embulk-output-gcs-0.2.0.jar
67
68
  - classpath/google-api-client-1.19.1.jar
68
69
  - classpath/google-api-services-storage-v1-rev28-1.19.1.jar
69
70
  - classpath/google-http-client-1.19.0.jar
Binary file