embulk-output-elasticsearch 0.1.8 → 0.2.0

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: 0c0c560040a57c47a8ebb93d8fe09ea9c27d0877
4
- data.tar.gz: bb7e6b43e092b88266468f254c66923a53abaf71
3
+ metadata.gz: 17a82e00d22fd47a3f0921903a8b2210c0ef938c
4
+ data.tar.gz: accef942b8a09e8700477fc74883693702eaae0e
5
5
  SHA512:
6
- metadata.gz: 3dc3769243508bea8270ea41f99d7efaa26222feec9f34878bd234fee9a671bc084c2f62f4aff519ab7f5b3183a30183d81279ec7fdcc91bf0e2900849c8c8f9
7
- data.tar.gz: 86eabe54f80a8801add35089f29c643c2b6821b7032c116a43768d13d75ed88c85a83e404436942715448d4eb43023f7eae8bee55580bd05fdb2f162e1f013fa
6
+ metadata.gz: 7cee36d9a5099ce50c92fdf760777e1a9e6cc960a9d543486d8aad10b0244a97e87e1396e8e653759f16a44ae77a5d9cb66b8be1682221d2b1337b900156c8c9
7
+ data.tar.gz: 75288939178b00e2d612f640c07fee9f0b86b21d1b5d17e4b15c93b2be97cb32e616a042302bf653d5aef09ce94ad790a481d6a952240d3d7700f5c10a29c1d2
data/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ ## 0.2.0 - 2016-01-26
2
+
3
+ * [new feature] Support Elasticsearch 2.x [#12](https://github.com/muga/embulk-output-elasticsearch/pull/12)
4
+ * [new feature] Added replace mode [#15](https://github.com/muga/embulk-output-elasticsearch/pull/15)
5
+ * [maintenance] Fix id param's behavior [#14](https://github.com/muga/embulk-output-elasticsearch/pull/14)
6
+ * [maintenance] Added unit tests [#17](https://github.com/muga/embulk-output-elasticsearch/pull/17)
7
+ * [maintenance] Upgraded Embulk to v0.7.7
8
+
9
+ ## 0.1.8 - 2015-08-19
10
+
11
+ * [maintenance] Upgraded Embulk to v0.7.0
12
+ * [maintenance] Upgraded Elasticsearch to v1.5.2
13
+
14
+ ## 0.1.7 - 2015-05-09
15
+
16
+ * [maintenance] Fixed handling null value [#10](https://github.com/muga/embulk-output-elasticsearch/pull/10)
17
+
18
+ ## 0.1.6 - 2015-04-14
19
+
20
+ * [new feature] Added bulk_size parameter [#8](https://github.com/muga/embulk-output-elasticsearch/pull/8)
21
+
22
+ ## 0.1.5 - 2015-03-26
23
+
24
+ * [new feature] Added cluster_name parameter [#7](https://github.com/muga/embulk-output-elasticsearch/pull/7)
25
+
26
+ ## 0.1.4 - 2015-03-19
27
+
28
+ * [maintenance] Fixed parameter names index_name to index, doc_id_column to id. [#5](https://github.com/muga/embulk-output-elasticsearch/pull/5)
29
+ * [maintenance] Fixed typo at parameter [#6](https://github.com/muga/embulk-output-elasticsearch/pull/6)
30
+
31
+ ## 0.1.3 - 2015-02-25
32
+
33
+ * [new feature] Supported timestamp column [#4](https://github.com/muga/embulk-output-elasticsearch/pull/4)
34
+
35
+ ## 0.1.2 - 2015-02-24
36
+
37
+ ## 0.1.1 - 2015-02-16
38
+
39
+ ## 0.1.0 - 2015-02-16
data/README.md CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  ## Configuration
11
11
 
12
+ - **mode**: "insert" or "replace". See below(string, optional, default is insert)
12
13
  - **nodes**: list of nodes. nodes are pairs of host and port (list, required)
13
14
  - **cluster_name**: name of the cluster (string, default is "elasticsearch")
14
15
  - **index**: index name (string, required)
@@ -18,11 +19,38 @@
18
19
  - **bulk_size**: Sets when to flush a new bulk request based on the size of actions currently added. (long, default is 5242880)
19
20
  - **concurrent_requests**: concurrent_requests (int, default is 5)
20
21
 
22
+ ### Modes
23
+
24
+ #### insert:
25
+
26
+ default.
27
+ This mode writes data to existing index.
28
+
29
+ #### replace:
30
+
31
+ 1. Create new temporary index
32
+ 2. Insert data into the new index
33
+ 3. replace the alias with the new index. If alias doesn't exists, plugin will create new alias.
34
+ 4. Delete existing (old) index if exists
35
+
36
+ Index should not exists with the same name as the alias
37
+
38
+ ```yaml
39
+ out:
40
+ type: elasticsearch
41
+ mode: replace
42
+ nodes:
43
+ - {host: localhost, port: 9300}
44
+ index: <alias name> # plugin generates index name like <index>_%Y%m%d-%H%M%S
45
+ index_type: <index type>
46
+ ```
47
+
21
48
  ## Example
22
49
 
23
50
  ```yaml
24
51
  out:
25
52
  type: elasticsearch
53
+ mode: insert
26
54
  nodes:
27
55
  - {host: localhost, port: 9300}
28
56
  index: <index name>
@@ -32,5 +60,53 @@ out:
32
60
  ## Build
33
61
 
34
62
  ```
35
- $ ./gradlew gem
63
+ $ ./gradlew gem # -t to watch change of files and rebuild continuously
36
64
  ```
65
+
66
+ ## Test
67
+
68
+ ```
69
+ $ ./gradlew test # -t to watch change of files and rebuild continuously
70
+ ```
71
+
72
+ To run unit tests, we need to configure the following environment variables.
73
+
74
+ When environment variables are not set, skip almost test cases.
75
+
76
+ ```
77
+ ES_HOST
78
+ ES_PORT(optional, if needed, default: 9300)
79
+ ES_INDEX
80
+ ES_INDEX_TYPE
81
+ ```
82
+
83
+ If you're using Mac OS X El Capitan and GUI Applications(IDE), like as follows.
84
+ ```
85
+ $ vi ~/Library/LaunchAgents/environment.plist
86
+ <?xml version="1.0" encoding="UTF-8"?>
87
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
88
+ <plist version="1.0">
89
+ <dict>
90
+ <key>Label</key>
91
+ <string>my.startup</string>
92
+ <key>ProgramArguments</key>
93
+ <array>
94
+ <string>sh</string>
95
+ <string>-c</string>
96
+ <string>
97
+ launchctl setenv ES_HOST example.com
98
+ launchctl setenv ES_PORT 9300
99
+ launchctl setenv ES_INDEX embulk
100
+ launchctl setenv ES_INDEX_TYPE embulk
101
+ </string>
102
+ </array>
103
+ <key>RunAtLoad</key>
104
+ <true/>
105
+ </dict>
106
+ </plist>
107
+
108
+ $ launchctl load ~/Library/LaunchAgents/environment.plist
109
+ $ launchctl getenv ES_INDEX //try to get value.
110
+
111
+ Then start your applications.
112
+ ```
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 {
@@ -13,18 +14,20 @@ configurations {
13
14
  provided
14
15
  }
15
16
 
16
- version = "0.1.8"
17
+ version = "0.2.0"
17
18
 
18
19
  compileJava.options.encoding = 'UTF-8' // source encoding
19
20
  sourceCompatibility = 1.7
20
21
  targetCompatibility = 1.7
21
22
 
22
23
  dependencies {
23
- compile "org.embulk:embulk-core:0.7.0"
24
- provided "org.embulk:embulk-core:0.7.0"
25
- compile 'org.elasticsearch:elasticsearch:1.5.2'
24
+ compile "org.embulk:embulk-core:0.7.7"
25
+ provided "org.embulk:embulk-core:0.7.7"
26
+ compile 'org.elasticsearch:elasticsearch:2.0.0'
27
+
26
28
  testCompile "junit:junit:4.+"
27
- testCompile "org.mockito:mockito-core:1.+"
29
+ testCompile "org.embulk:embulk-core:0.7.7:tests"
30
+ testCompile "org.embulk:embulk-standards:0.7.7"
28
31
  }
29
32
 
30
33
  task classpath(type: Copy, dependsOn: ["jar"]) {
@@ -67,4 +70,12 @@ Gem::Specification.new do |spec|
67
70
  spec.add_development_dependency "test-unit", ["~> 3.0.2"]
68
71
  end
69
72
  /$)
70
- }
73
+ }
74
+
75
+ jacocoTestReport {
76
+ afterEvaluate {
77
+ classDirectories = files(classDirectories.files.collect {
78
+ fileTree(dir: it, exclude: 'org/embulk/output/elasticsearch/ElasticsearchOutputPlugin$1.class')
79
+ })
80
+ }
81
+ }
@@ -1,9 +1,18 @@
1
1
  package org.embulk.output.elasticsearch;
2
2
 
3
- import com.google.common.base.Optional;
4
- import com.google.common.base.Throwables;
5
- import com.google.common.collect.ImmutableList;
6
- import com.google.inject.Inject;
3
+ import java.io.IOException;
4
+ import java.text.SimpleDateFormat;
5
+ import java.util.ArrayList;
6
+ import java.util.Date;
7
+ import java.util.List;
8
+ import java.util.Locale;
9
+ import java.util.concurrent.TimeUnit;
10
+ import java.net.InetAddress;
11
+ import java.net.UnknownHostException;
12
+
13
+ import com.fasterxml.jackson.annotation.JsonCreator;
14
+ import com.fasterxml.jackson.annotation.JsonValue;
15
+
7
16
  import org.elasticsearch.action.bulk.BulkItemResponse;
8
17
  import org.elasticsearch.action.bulk.BulkProcessor;
9
18
  import org.elasticsearch.action.bulk.BulkRequest;
@@ -12,38 +21,44 @@ import org.elasticsearch.action.index.IndexRequest;
12
21
  import org.elasticsearch.client.Client;
13
22
  import org.elasticsearch.client.Requests;
14
23
  import org.elasticsearch.client.transport.TransportClient;
15
- import org.elasticsearch.common.unit.ByteSizeValue;
16
- import org.elasticsearch.common.unit.ByteSizeUnit;
17
- import org.elasticsearch.common.settings.ImmutableSettings;
24
+ import org.elasticsearch.cluster.metadata.AliasMetaData;
25
+ import org.elasticsearch.cluster.metadata.AliasOrIndex;
26
+ import org.elasticsearch.common.collect.ImmutableOpenMap;
18
27
  import org.elasticsearch.common.settings.Settings;
19
28
  import org.elasticsearch.common.transport.InetSocketTransportAddress;
29
+ import org.elasticsearch.common.unit.ByteSizeValue;
20
30
  import org.elasticsearch.common.xcontent.XContentBuilder;
21
31
  import org.elasticsearch.common.xcontent.XContentFactory;
22
- import org.elasticsearch.node.Node;
23
- import org.elasticsearch.node.NodeBuilder;
24
- import org.embulk.config.TaskReport;
32
+ import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
33
+ import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
34
+ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
35
+ import org.elasticsearch.index.IndexNotFoundException;
36
+ import org.elasticsearch.indices.InvalidAliasNameException;
37
+
25
38
  import org.embulk.config.Config;
26
39
  import org.embulk.config.ConfigDefault;
27
40
  import org.embulk.config.ConfigDiff;
41
+ import org.embulk.config.ConfigException;
28
42
  import org.embulk.config.ConfigSource;
29
43
  import org.embulk.config.Task;
44
+ import org.embulk.config.TaskReport;
30
45
  import org.embulk.config.TaskSource;
31
46
  import org.embulk.spi.Column;
47
+ import org.embulk.spi.ColumnVisitor;
32
48
  import org.embulk.spi.Exec;
33
49
  import org.embulk.spi.OutputPlugin;
34
50
  import org.embulk.spi.Page;
35
51
  import org.embulk.spi.PageReader;
36
52
  import org.embulk.spi.Schema;
37
- import org.embulk.spi.ColumnVisitor;
38
53
  import org.embulk.spi.TransactionalPageOutput;
54
+ import org.embulk.spi.time.Timestamp;
55
+ import org.embulk.spi.type.Types;
39
56
  import org.slf4j.Logger;
40
57
 
41
- import java.io.IOException;
42
- import java.util.Date;
43
- import java.util.List;
44
- import java.util.concurrent.TimeUnit;
45
-
46
- import static com.google.common.base.Preconditions.checkState;
58
+ import com.google.common.base.Optional;
59
+ import com.google.common.base.Throwables;
60
+ import com.google.inject.Inject;
61
+ import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
47
62
 
48
63
  public class ElasticsearchOutputPlugin
49
64
  implements OutputPlugin
@@ -62,6 +77,10 @@ public class ElasticsearchOutputPlugin
62
77
  public interface PluginTask
63
78
  extends Task
64
79
  {
80
+ @Config("mode")
81
+ @ConfigDefault("\"insert\"")
82
+ public Mode getMode();
83
+
65
84
  @Config("nodes")
66
85
  public List<NodeAddressTask> getNodes();
67
86
 
@@ -71,6 +90,12 @@ public class ElasticsearchOutputPlugin
71
90
 
72
91
  @Config("index")
73
92
  public String getIndex();
93
+ public void setIndex(String indexName);
94
+
95
+ @Config("alias")
96
+ @ConfigDefault("null")
97
+ public Optional<String> getAlias();
98
+ public void setAlias(Optional<String> aliasName);
74
99
 
75
100
  @Config("index_type")
76
101
  public String getType();
@@ -108,21 +133,15 @@ public class ElasticsearchOutputPlugin
108
133
 
109
134
  // confirm that a client can be initialized
110
135
  try (Client client = createClient(task)) {
111
- }
112
-
113
- // check that id is included in the schema or not if the id is not null.
114
- if (task.getId().isPresent()) {
115
- String id = task.getId().get();
116
- boolean found = false;
117
- for (Column column : schema.getColumns()) {
118
- if (column.equals(id)) {
119
- found = true;
136
+ log.info(String.format("Executing plugin with '%s' mode.", task.getMode()));
137
+ if (task.getMode().equals(Mode.REPLACE)) {
138
+ task.setAlias(Optional.of(task.getIndex()));
139
+ task.setIndex(generateNewIndexName(task.getIndex()));
140
+ if (isExistsIndex(task.getAlias().orNull(), client) && !isAlias(task.getAlias().orNull(), client)) {
141
+ throw new ConfigException(String.format("Invalid alias name [%s], an index exists with the same name as the alias", task.getAlias().orNull()));
120
142
  }
121
143
  }
122
- checkState(found, "id is not included in column names of the Schema.");
123
- }
124
-
125
- try {
144
+ log.info(String.format("Inserting data into index[%s]", task.getIndex()));
126
145
  control.run(task.dump());
127
146
  } catch (Exception e) {
128
147
  throw Throwables.propagate(e);
@@ -145,19 +164,31 @@ public class ElasticsearchOutputPlugin
145
164
  public void cleanup(TaskSource taskSource,
146
165
  Schema schema, int processorCount,
147
166
  List<TaskReport> successTaskReports)
148
- { }
167
+ {
168
+ final PluginTask task = taskSource.loadTask(PluginTask.class);
169
+ if (task.getMode().equals(Mode.REPLACE)) {
170
+ try (Client client = createClient(task)) {
171
+ reAssignAlias(task.getAlias().orNull(), task.getIndex(), client);
172
+ } catch (IndexNotFoundException | InvalidAliasNameException e) {
173
+ throw new ConfigException(e);
174
+ }
175
+ }
176
+ }
149
177
 
150
178
  private Client createClient(final PluginTask task)
151
179
  {
152
180
  // @see http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api/current/client.html
153
- Settings settings = ImmutableSettings.settingsBuilder()
154
- .classLoader(Settings.class.getClassLoader())
181
+ Settings settings = Settings.settingsBuilder()
155
182
  .put("cluster.name", task.getClusterName())
156
183
  .build();
157
- TransportClient client = new TransportClient(settings);
184
+ TransportClient client = TransportClient.builder().settings(settings).build();
158
185
  List<NodeAddressTask> nodes = task.getNodes();
159
186
  for (NodeAddressTask node : nodes) {
160
- client.addTransportAddress(new InetSocketTransportAddress(node.getHost(), node.getPort()));
187
+ try {
188
+ client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(node.getHost()), node.getPort()));
189
+ } catch (UnknownHostException e) {
190
+ Throwables.propagate(e);
191
+ }
161
192
  }
162
193
  return client;
163
194
  }
@@ -208,7 +239,6 @@ public class ElasticsearchOutputPlugin
208
239
  int processorIndex)
209
240
  {
210
241
  final PluginTask task = taskSource.loadTask(PluginTask.class);
211
-
212
242
  Client client = createClient(task);
213
243
  BulkProcessor bulkProcessor = newBulkProcessor(task, client);
214
244
  ElasticsearchPageOutput pageOutput = new ElasticsearchPageOutput(task, client, bulkProcessor);
@@ -224,6 +254,7 @@ public class ElasticsearchOutputPlugin
224
254
  private BulkProcessor bulkProcessor;
225
255
 
226
256
  private PageReader pageReader;
257
+ private Column idColumn;
227
258
 
228
259
  private final String index;
229
260
  private final String type;
@@ -244,6 +275,7 @@ public class ElasticsearchOutputPlugin
244
275
  void open(final Schema schema)
245
276
  {
246
277
  pageReader = new PageReader(schema);
278
+ idColumn = (id == null) ? null : schema.lookupColumn(id);
247
279
  }
248
280
 
249
281
  @Override
@@ -342,7 +374,7 @@ public class ElasticsearchOutputPlugin
342
374
  });
343
375
 
344
376
  contextBuilder.endObject();
345
- bulkProcessor.add(newIndexRequest().source(contextBuilder));
377
+ bulkProcessor.add(newIndexRequest(getIdValue(idColumn)).source(contextBuilder));
346
378
 
347
379
  } catch (IOException e) {
348
380
  Throwables.propagate(e); // TODO error handling
@@ -350,9 +382,33 @@ public class ElasticsearchOutputPlugin
350
382
  }
351
383
  }
352
384
 
353
- private IndexRequest newIndexRequest()
385
+ /**
386
+ * @param inputColumn
387
+ * @return
388
+ */
389
+ private String getIdValue(Column inputColumn) {
390
+ if (inputColumn == null) return null;
391
+ if (pageReader.isNull(inputColumn)) return null;
392
+ String idValue = null;
393
+ if (Types.STRING.equals(inputColumn.getType())) {
394
+ idValue = pageReader.getString(inputColumn);
395
+ } else if (Types.BOOLEAN.equals(inputColumn.getType())) {
396
+ idValue = pageReader.getBoolean(inputColumn) + "";
397
+ } else if (Types.DOUBLE.equals(inputColumn.getType())) {
398
+ idValue = pageReader.getDouble(inputColumn) + "";
399
+ } else if (Types.LONG.equals(inputColumn.getType())) {
400
+ idValue = pageReader.getLong(inputColumn) + "";
401
+ } else if (Types.TIMESTAMP.equals(inputColumn.getType())) {
402
+ idValue = pageReader.getTimestamp(inputColumn).toString();
403
+ } else {
404
+ idValue = null;
405
+ }
406
+ return idValue;
407
+ }
408
+
409
+ private IndexRequest newIndexRequest(String idValue)
354
410
  {
355
- return Requests.indexRequest(index).type(type).id(id);
411
+ return Requests.indexRequest(index).type(type).id(idValue);
356
412
  }
357
413
 
358
414
  @Override
@@ -400,4 +456,91 @@ public class ElasticsearchOutputPlugin
400
456
  }
401
457
 
402
458
  }
459
+
460
+ public enum Mode
461
+ {
462
+ INSERT,
463
+ REPLACE;
464
+
465
+ @JsonValue
466
+ @Override
467
+ public String toString()
468
+ {
469
+ return name().toLowerCase(Locale.ENGLISH);
470
+ }
471
+
472
+ @JsonCreator
473
+ public static Mode fromString(String value)
474
+ {
475
+ switch (value) {
476
+ case "insert":
477
+ return INSERT;
478
+ case "replace":
479
+ return REPLACE;
480
+ default:
481
+ throw new ConfigException(String.format("Unknown mode '%s'. Supported modes are insert, truncate_insert, replace", value));
482
+ }
483
+ }
484
+ }
485
+
486
+ private void reAssignAlias(String aliasName, String newIndexName, Client client)
487
+ throws IndexNotFoundException, InvalidAliasNameException
488
+ {
489
+ if (!isExistsAlias(aliasName, client)) {
490
+ client.admin().indices().prepareAliases()
491
+ .addAlias(newIndexName, aliasName)
492
+ .execute().actionGet();
493
+ log.info(String.format("Assigned alias[%s] to index[%s]", aliasName, newIndexName));
494
+ } else {
495
+ List<String> oldIndices = getIndexByAlias(aliasName, client);
496
+ client.admin().indices().prepareAliases()
497
+ .removeAlias(oldIndices.toArray(new String[oldIndices.size()]), aliasName)
498
+ .addAlias(newIndexName, aliasName)
499
+ .execute().actionGet();
500
+ log.info(String.format("Reassigned alias[%s] from index%s to index[%s]", aliasName, oldIndices, newIndexName));
501
+ for (String index : oldIndices) {
502
+ deleteIndex(index, client);
503
+ }
504
+ }
505
+ }
506
+
507
+ private void deleteIndex(String indexName, Client client)
508
+ {
509
+ client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet();
510
+ log.info(String.format("Deleted Index [%s]", indexName));
511
+ }
512
+
513
+ private List<String> getIndexByAlias(String aliasName, Client client)
514
+ {
515
+ ImmutableOpenMap<String, List<AliasMetaData>> map = client.admin().indices().getAliases(new GetAliasesRequest(aliasName))
516
+ .actionGet().getAliases();
517
+ List<String> indices = new ArrayList<>();
518
+ for (ObjectObjectCursor<String, List<AliasMetaData>> c : map) {
519
+ indices.add(c.key);
520
+ }
521
+
522
+ return indices;
523
+ }
524
+
525
+ private boolean isExistsAlias(String aliasName, Client client)
526
+ {
527
+ return client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().hasAlias(aliasName);
528
+ }
529
+
530
+ private boolean isExistsIndex(String indexName, Client client)
531
+ {
532
+ return client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().hasIndex(indexName);
533
+ }
534
+
535
+ private boolean isAlias(String aliasName, Client client)
536
+ {
537
+ AliasOrIndex aliasOrIndex = client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().getAliasAndIndexLookup().get(aliasName);
538
+ return aliasOrIndex != null && aliasOrIndex.isAlias();
539
+ }
540
+
541
+ public String generateNewIndexName(String indexName)
542
+ {
543
+ Timestamp time = Exec.getTransactionTime();
544
+ return indexName + new SimpleDateFormat("_yyyyMMdd-HHmmss").format(time.toEpochMilli());
545
+ }
403
546
  }
@@ -1,5 +1,484 @@
1
1
  package org.embulk.output.elasticsearch;
2
2
 
3
+ import java.io.ByteArrayOutputStream;
4
+ import java.io.InputStream;
5
+ import java.io.IOException;
6
+ import java.lang.reflect.InvocationTargetException;
7
+ import java.lang.reflect.Method;
8
+ import java.net.UnknownHostException;
9
+ import java.text.ParseException;
10
+ import java.text.SimpleDateFormat;
11
+ import java.util.Arrays;
12
+ import java.util.List;
13
+ import java.util.Map;
14
+ import java.security.GeneralSecurityException;
15
+
16
+ import com.google.common.collect.Lists;
17
+ import com.google.common.collect.ImmutableList;
18
+ import com.google.common.collect.ImmutableMap;
19
+ import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
20
+ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
21
+ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
22
+ import org.elasticsearch.action.get.GetResponse;
23
+ import org.elasticsearch.client.Client;
24
+ import org.embulk.EmbulkTestRuntime;
25
+ import org.embulk.config.ConfigException;
26
+ import org.embulk.config.TaskReport;
27
+ import org.embulk.config.TaskSource;
28
+ import org.embulk.config.ConfigSource;
29
+ import org.embulk.spi.Exec;
30
+ import org.embulk.spi.OutputPlugin;
31
+ import org.embulk.spi.Page;
32
+ import org.embulk.spi.PageTestUtils;
33
+ import org.embulk.spi.Schema;
34
+ import org.embulk.spi.time.Timestamp;
35
+ import org.embulk.spi.TransactionalPageOutput;
36
+ import org.embulk.spi.TestPageBuilderReader.MockPageOutput;
37
+ import org.embulk.standards.CsvParserPlugin;
38
+ import org.embulk.output.elasticsearch.ElasticsearchOutputPlugin.PluginTask;
39
+ import org.junit.Before;
40
+ import org.junit.BeforeClass;
41
+ import org.junit.Rule;
42
+ import org.junit.Test;
43
+ import static org.junit.Assert.assertEquals;
44
+ import static org.junit.Assert.assertTrue;
45
+ import static org.junit.Assume.assumeNotNull;
46
+
3
47
  public class TestElasticsearchOutputPlugin
4
48
  {
49
+ private static String ES_HOST;
50
+ private static int ES_PORT;
51
+ private static List ES_NODES;
52
+ private static String ES_CLUSTER_NAME;
53
+ private static String ES_INDEX;
54
+ private static String ES_INDEX_TYPE;
55
+ private static String ES_ID;
56
+ private static int ES_BULK_ACTIONS;
57
+ private static int ES_BULK_SIZE;
58
+ private static int ES_CONCURRENT_REQUESTS;
59
+ private static String PATH_PREFIX;
60
+
61
+ private MockPageOutput pageOutput;
62
+
63
+ final String ES_TEST_INDEX = "index_for_unittest";
64
+ final String ES_TEST_INDEX2 = "index_for_unittest2";
65
+ final String ES_TEST_ALIAS = "alias_for_unittest";
66
+
67
+ /*
68
+ * This test case requires environment variables
69
+ * ES_HOST
70
+ * ES_INDEX
71
+ * ES_INDEX_TYPE
72
+ */
73
+ @BeforeClass
74
+ public static void initializeConstant()
75
+ {
76
+ ES_HOST = System.getenv("ES_HOST") != null ? System.getenv("ES_HOST") : "";
77
+ ES_PORT = System.getenv("ES_PORT") != null ? Integer.valueOf(System.getenv("ES_PORT")) : 9300;
78
+
79
+ ES_CLUSTER_NAME = System.getenv("ES_CLUSTER_NAME") != null ? System.getenv("ES_CLUSTER_NAME") : "";
80
+ ES_INDEX = System.getenv("ES_INDEX");
81
+ ES_INDEX_TYPE = System.getenv("ES_INDEX_TYPE");
82
+ ES_ID = "id";
83
+ ES_BULK_ACTIONS = System.getenv("ES_BULK_ACTIONS") != null ? Integer.valueOf(System.getenv("ES_BULK_ACTIONS")) : 1000;
84
+ ES_BULK_SIZE = System.getenv("ES_BULK_SIZE") != null ? Integer.valueOf(System.getenv("ES_BULK_SIZE")) : 5242880;
85
+ ES_CONCURRENT_REQUESTS = System.getenv("ES_CONCURRENT_REQUESTS") != null ? Integer.valueOf(System.getenv("ES_CONCURRENT_REQUESTS")) : 5;
86
+
87
+ assumeNotNull(ES_HOST, ES_INDEX, ES_INDEX_TYPE);
88
+
89
+ ES_NODES = Arrays.asList(ImmutableMap.of("host", ES_HOST, "port", ES_PORT));
90
+
91
+ PATH_PREFIX = ElasticsearchOutputPlugin.class.getClassLoader().getResource("sample_01.csv").getPath();
92
+ }
93
+
94
+
95
+ @Rule
96
+ public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
97
+ private ElasticsearchOutputPlugin plugin;
98
+
99
+ @Before
100
+ public void createResources()
101
+ throws GeneralSecurityException, NoSuchMethodException,
102
+ IllegalAccessException, InvocationTargetException
103
+ {
104
+ ConfigSource config = config();
105
+ plugin = new ElasticsearchOutputPlugin();
106
+ PluginTask task = config.loadConfig(PluginTask.class);
107
+ pageOutput = new MockPageOutput();
108
+
109
+ Method createClient = ElasticsearchOutputPlugin.class.getDeclaredMethod("createClient", PluginTask.class);
110
+ createClient.setAccessible(true);
111
+ try (Client client = (Client) createClient.invoke(plugin, task)) {
112
+ // Delete alias
113
+ if (client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().hasAlias(ES_TEST_ALIAS)) {
114
+ client.admin().indices().delete(new DeleteIndexRequest(ES_TEST_ALIAS)).actionGet();
115
+ }
116
+
117
+ // Delete index
118
+ if (client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().hasIndex(ES_TEST_INDEX)) {
119
+ client.admin().indices().delete(new DeleteIndexRequest(ES_TEST_INDEX)).actionGet();
120
+ }
121
+
122
+ if (client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().hasIndex(ES_TEST_INDEX2)) {
123
+ client.admin().indices().delete(new DeleteIndexRequest(ES_TEST_INDEX2)).actionGet();
124
+ }
125
+ }
126
+ }
127
+
128
+ @Test
129
+ public void testDefaultValues()
130
+ {
131
+ ConfigSource config = config();
132
+ ElasticsearchOutputPlugin.PluginTask task = config.loadConfig(PluginTask.class);
133
+ assertEquals(ES_INDEX, task.getIndex());
134
+ }
135
+
136
+ @Test
137
+ public void testDefaultValuesNull()
138
+ {
139
+ ConfigSource config = Exec.newConfigSource()
140
+ .set("in", inputConfig())
141
+ .set("parser", parserConfig(schemaConfig()))
142
+ .set("type", "elasticsearch")
143
+ .set("mode", "") // NULL
144
+ .set("nodes", ES_NODES)
145
+ .set("cluster_name", ES_CLUSTER_NAME)
146
+ .set("index", ES_INDEX)
147
+ .set("index_type", ES_INDEX_TYPE)
148
+ .set("id", ES_ID)
149
+ .set("bulk_actions", ES_BULK_ACTIONS)
150
+ .set("bulk_size", ES_BULK_SIZE)
151
+ .set("concurrent_requests", ES_CONCURRENT_REQUESTS
152
+ );
153
+ Schema schema = config.getNested("parser").loadConfig(CsvParserPlugin.PluginTask.class).getSchemaConfig().toSchema();
154
+ try {
155
+ plugin.transaction(config, schema, 0, new OutputPlugin.Control()
156
+ {
157
+ @Override
158
+ public List<TaskReport> run(TaskSource taskSource)
159
+ {
160
+ return Lists.newArrayList(Exec.newTaskReport());
161
+ }
162
+ });
163
+ } catch (Throwable t) {
164
+ if (t instanceof RuntimeException) {
165
+ assertTrue(t.getCause().getCause() instanceof ConfigException);
166
+ }
167
+ }
168
+ }
169
+
170
+ @Test
171
+ public void testResume()
172
+ {
173
+ ConfigSource config = config();
174
+ Schema schema = config.getNested("parser").loadConfig(CsvParserPlugin.PluginTask.class).getSchemaConfig().toSchema();
175
+ PluginTask task = config.loadConfig(PluginTask.class);
176
+ plugin.resume(task.dump(), schema, 0, new OutputPlugin.Control()
177
+ {
178
+ @Override
179
+ public List<TaskReport> run(TaskSource taskSource)
180
+ {
181
+ return Lists.newArrayList(Exec.newTaskReport());
182
+ }
183
+ });
184
+ }
185
+
186
+ @Test
187
+ public void testTransaction()
188
+ {
189
+ ConfigSource config = Exec.newConfigSource()
190
+ .set("in", inputConfig())
191
+ .set("parser", parserConfig(schemaConfig()))
192
+ .set("type", "elasticsearch")
193
+ .set("mode", "replace")
194
+ .set("nodes", ES_NODES)
195
+ .set("cluster_name", ES_CLUSTER_NAME)
196
+ .set("index", ES_INDEX)
197
+ .set("index_type", ES_INDEX_TYPE)
198
+ .set("id", ES_ID)
199
+ .set("bulk_actions", ES_BULK_ACTIONS)
200
+ .set("bulk_size", ES_BULK_SIZE)
201
+ .set("concurrent_requests", ES_CONCURRENT_REQUESTS
202
+ );
203
+ Schema schema = config.getNested("parser").loadConfig(CsvParserPlugin.PluginTask.class).getSchemaConfig().toSchema();
204
+ plugin.transaction(config, schema, 0, new OutputPlugin.Control()
205
+ {
206
+ @Override
207
+ public List<TaskReport> run(TaskSource taskSource)
208
+ {
209
+ return Lists.newArrayList(Exec.newTaskReport());
210
+ }
211
+ });
212
+ // no error happens
213
+ }
214
+
215
+ @Test
216
+ public void testOutputByOpen()
217
+ throws GeneralSecurityException, IOException, NoSuchMethodException,
218
+ IllegalAccessException, InvocationTargetException, ParseException
219
+ {
220
+ ConfigSource config = config();
221
+ Schema schema = config.getNested("parser").loadConfig(CsvParserPlugin.PluginTask.class).getSchemaConfig().toSchema();
222
+ PluginTask task = config.loadConfig(PluginTask.class);
223
+ plugin.transaction(config, schema, 0, new OutputPlugin.Control() {
224
+ @Override
225
+ public List<TaskReport> run(TaskSource taskSource) {
226
+ return Lists.newArrayList(Exec.newTaskReport());
227
+ }
228
+ });
229
+ TransactionalPageOutput output = plugin.open(task.dump(), schema, 0);
230
+
231
+ List<Page> pages = PageTestUtils.buildPage(runtime.getBufferAllocator(), schema, 1L, 32864L, Timestamp.ofEpochSecond(1422386629), Timestamp.ofEpochSecond(1422316800), true, 123.45, "embulk");
232
+ assertEquals(1, pages.size());
233
+ for (Page page : pages) {
234
+ output.add(page);
235
+ }
236
+
237
+ output.finish();
238
+ output.commit();
239
+
240
+ Method createClient = ElasticsearchOutputPlugin.class.getDeclaredMethod("createClient", PluginTask.class);
241
+ createClient.setAccessible(true);
242
+ try (Client client = (Client) createClient.invoke(plugin, task)) {
243
+ GetResponse response = client.prepareGet(ES_INDEX, ES_INDEX_TYPE, "1").execute().actionGet();
244
+ assertTrue(response.isExists());
245
+ if (response.isExists()) {
246
+ Map<String, Object> map = response.getSourceAsMap();
247
+ assertEquals(1, map.get("id"));
248
+ assertEquals(32864, map.get("account"));
249
+ assertEquals("2015-01-27T19:23:49.000Z", map.get("time"));
250
+ assertEquals("2015-01-27T00:00:00.000Z", map.get("purchase"));
251
+ assertEquals(true, map.get("flg"));
252
+ assertEquals(123.45, map.get("score"));
253
+ assertEquals("embulk", map.get("comment"));
254
+ }
255
+ }
256
+ }
257
+
258
+ @Test
259
+ public void testOpenAbort()
260
+ {
261
+ ConfigSource config = config();
262
+ Schema schema = config.getNested("parser").loadConfig(CsvParserPlugin.PluginTask.class).getSchemaConfig().toSchema();
263
+ PluginTask task = config.loadConfig(PluginTask.class);
264
+ TransactionalPageOutput output = plugin.open(task.dump(), schema, 0);
265
+ output.abort();
266
+ // no error happens.
267
+ }
268
+
269
+ @Test
270
+ public void testCreateClientThrowsException()
271
+ throws GeneralSecurityException, IOException, NoSuchMethodException,
272
+ IllegalAccessException, InvocationTargetException
273
+ {
274
+ ConfigSource config = Exec.newConfigSource()
275
+ .set("in", inputConfig())
276
+ .set("parser", parserConfig(schemaConfig()))
277
+ .set("type", "elasticsearch")
278
+ .set("mode", "replace")
279
+ .set("nodes", Arrays.asList(ImmutableMap.of("host", "unknown-host", "port", 9300)))
280
+ .set("cluster_name", ES_CLUSTER_NAME)
281
+ .set("index", ES_INDEX)
282
+ .set("index_type", ES_INDEX_TYPE)
283
+ .set("id", ES_ID)
284
+ .set("bulk_actions", ES_BULK_ACTIONS)
285
+ .set("bulk_size", ES_BULK_SIZE)
286
+ .set("concurrent_requests", ES_CONCURRENT_REQUESTS
287
+ );
288
+ PluginTask task = config.loadConfig(PluginTask.class);
289
+
290
+ Method createClient = ElasticsearchOutputPlugin.class.getDeclaredMethod("createClient", PluginTask.class);
291
+ createClient.setAccessible(true);
292
+ try (Client client = (Client) createClient.invoke(plugin, task)) {
293
+ } catch (Throwable t) {
294
+ if (t instanceof InvocationTargetException) {
295
+ assertTrue(t.getCause().getCause() instanceof UnknownHostException);
296
+ }
297
+ }
298
+ }
299
+
300
+ @Test
301
+ public void testMode()
302
+ {
303
+ assertEquals(2, ElasticsearchOutputPlugin.Mode.values().length);
304
+ assertEquals(ElasticsearchOutputPlugin.Mode.INSERT, ElasticsearchOutputPlugin.Mode.valueOf("INSERT"));
305
+ }
306
+
307
+ @Test(expected = ConfigException.class)
308
+ public void testModeThrowsConfigException()
309
+ {
310
+ ElasticsearchOutputPlugin.Mode.fromString("non-exists-mode");
311
+ }
312
+
313
+ @Test
314
+ public void testDeleteIndex()
315
+ throws GeneralSecurityException, IOException, NoSuchMethodException,
316
+ IllegalAccessException, InvocationTargetException
317
+ {
318
+ ConfigSource config = config();
319
+ PluginTask task = config.loadConfig(PluginTask.class);
320
+
321
+ Method createClient = ElasticsearchOutputPlugin.class.getDeclaredMethod("createClient", PluginTask.class);
322
+ createClient.setAccessible(true);
323
+ try (Client client = (Client) createClient.invoke(plugin, task)) {
324
+ // Create Index
325
+ client.admin().indices().create(new CreateIndexRequest(ES_TEST_INDEX)).actionGet();
326
+
327
+ Method deleteIndex = ElasticsearchOutputPlugin.class.getDeclaredMethod("deleteIndex", String.class, Client.class);
328
+ deleteIndex.setAccessible(true);
329
+ deleteIndex.invoke(plugin, ES_TEST_INDEX, client);
330
+
331
+ assertEquals(false, client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().hasIndex(ES_TEST_INDEX));
332
+ }
333
+ }
334
+
335
+ @Test
336
+ public void testAlias()
337
+ throws GeneralSecurityException, IOException, NoSuchMethodException,
338
+ IllegalAccessException, InvocationTargetException
339
+ {
340
+ ConfigSource config = config();
341
+ PluginTask task = config.loadConfig(PluginTask.class);
342
+
343
+ Method createClient = ElasticsearchOutputPlugin.class.getDeclaredMethod("createClient", PluginTask.class);
344
+ createClient.setAccessible(true);
345
+ try (Client client = (Client) createClient.invoke(plugin, task)) {
346
+
347
+ Method isAlias = ElasticsearchOutputPlugin.class.getDeclaredMethod("isAlias", String.class, Client.class);
348
+ isAlias.setAccessible(true);
349
+
350
+ Method isExistsAlias = ElasticsearchOutputPlugin.class.getDeclaredMethod("isExistsAlias", String.class, Client.class);
351
+ isExistsAlias.setAccessible(true);
352
+
353
+ Method getIndexByAlias = ElasticsearchOutputPlugin.class.getDeclaredMethod("getIndexByAlias", String.class, Client.class);
354
+ getIndexByAlias.setAccessible(true);
355
+
356
+ Method reAssignAlias = ElasticsearchOutputPlugin.class.getDeclaredMethod("reAssignAlias", String.class, String.class, Client.class);
357
+ reAssignAlias.setAccessible(true);
358
+
359
+ assertEquals(false, isAlias.invoke(plugin, ES_TEST_ALIAS, client));
360
+ assertEquals(false, isExistsAlias.invoke(plugin, ES_TEST_ALIAS, client));
361
+ List<String> indicesBefore = (List<String>) getIndexByAlias.invoke(plugin, ES_TEST_ALIAS, client);
362
+ assertEquals(0, indicesBefore.size());
363
+
364
+ // Create Index
365
+ client.admin().indices().create(new CreateIndexRequest(ES_TEST_INDEX)).actionGet();
366
+ client.admin().indices().create(new CreateIndexRequest(ES_TEST_INDEX2)).actionGet();
367
+ // Assign Alias
368
+ reAssignAlias.invoke(plugin, ES_TEST_ALIAS, ES_TEST_INDEX, client);
369
+
370
+ assertEquals(true, isAlias.invoke(plugin, ES_TEST_ALIAS, client));
371
+ assertEquals(true, isExistsAlias.invoke(plugin, ES_TEST_ALIAS, client));
372
+ List<String> indicesAfter = (List<String>) getIndexByAlias.invoke(plugin, ES_TEST_ALIAS, client);
373
+ assertEquals(1, indicesAfter.size());
374
+
375
+ // ReAssginAlias
376
+ reAssignAlias.invoke(plugin, ES_TEST_ALIAS, ES_TEST_INDEX2, client);
377
+ List<String> indicesReassign = (List<String>) getIndexByAlias.invoke(plugin, ES_TEST_ALIAS, client);
378
+ assertEquals(1, indicesReassign.size());
379
+ }
380
+ }
381
+
382
+ @Test
383
+ public void testIsExistsIndex()
384
+ throws GeneralSecurityException, IOException, NoSuchMethodException,
385
+ IllegalAccessException, InvocationTargetException
386
+ {
387
+ ConfigSource config = config();
388
+ PluginTask task = config.loadConfig(PluginTask.class);
389
+
390
+ Method createClient = ElasticsearchOutputPlugin.class.getDeclaredMethod("createClient", PluginTask.class);
391
+ createClient.setAccessible(true);
392
+ try (Client client = (Client) createClient.invoke(plugin, task)) {
393
+ Method isExistsIndex = ElasticsearchOutputPlugin.class.getDeclaredMethod("isExistsIndex", String.class, Client.class);
394
+ isExistsIndex.setAccessible(true);
395
+
396
+ // Delete index
397
+ if (client.admin().cluster().state(new ClusterStateRequest()).actionGet().getState().getMetaData().hasIndex(ES_TEST_INDEX)) {
398
+ client.admin().indices().delete(new DeleteIndexRequest(ES_TEST_INDEX)).actionGet();
399
+ }
400
+ assertEquals(false, isExistsIndex.invoke(plugin, ES_TEST_INDEX, client));
401
+
402
+ // Create Index
403
+ client.admin().indices().create(new CreateIndexRequest(ES_TEST_INDEX)).actionGet();
404
+ assertEquals(true, isExistsIndex.invoke(plugin, ES_TEST_INDEX, client));
405
+ }
406
+ }
407
+
408
+ @Test
409
+ public void testGenerateNewIndex()
410
+ {
411
+ String newIndexName = plugin.generateNewIndexName(ES_INDEX);
412
+ Timestamp time = Exec.getTransactionTime();
413
+ assertEquals(ES_INDEX + new SimpleDateFormat("_yyyyMMdd-HHmmss").format(time.toEpochMilli()), newIndexName);
414
+ }
415
+
416
+ private byte[] convertInputStreamToByte(InputStream is) throws IOException
417
+ {
418
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
419
+ byte [] buffer = new byte[1024];
420
+ while(true) {
421
+ int len = is.read(buffer);
422
+ if(len < 0) {
423
+ break;
424
+ }
425
+ bo.write(buffer, 0, len);
426
+ }
427
+ return bo.toByteArray();
428
+ }
429
+
430
+ private ConfigSource config()
431
+ {
432
+ return Exec.newConfigSource()
433
+ .set("in", inputConfig())
434
+ .set("parser", parserConfig(schemaConfig()))
435
+ .set("type", "elasticsearch")
436
+ .set("mode", "insert")
437
+ .set("nodes", ES_NODES)
438
+ .set("cluster_name", ES_CLUSTER_NAME)
439
+ .set("index", ES_INDEX)
440
+ .set("index_type", ES_INDEX_TYPE)
441
+ .set("id", ES_ID)
442
+ .set("bulk_actions", ES_BULK_ACTIONS)
443
+ .set("bulk_size", ES_BULK_SIZE)
444
+ .set("concurrent_requests", ES_CONCURRENT_REQUESTS);
445
+ }
446
+
447
+ private ImmutableMap<String, Object> inputConfig()
448
+ {
449
+ ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
450
+ builder.put("type", "file");
451
+ builder.put("path_prefix", PATH_PREFIX);
452
+ builder.put("last_path", "");
453
+ return builder.build();
454
+ }
455
+
456
+ private ImmutableMap<String, Object> parserConfig(ImmutableList<Object> schemaConfig)
457
+ {
458
+ ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
459
+ builder.put("type", "csv");
460
+ builder.put("newline", "CRLF");
461
+ builder.put("delimiter", ",");
462
+ builder.put("quote", "\"");
463
+ builder.put("escape", "\"");
464
+ builder.put("trim_if_not_quoted", false);
465
+ builder.put("skip_header_lines", 1);
466
+ builder.put("allow_extra_columns", false);
467
+ builder.put("allow_optional_columns", false);
468
+ builder.put("columns", schemaConfig);
469
+ return builder.build();
470
+ }
471
+
472
+ private ImmutableList<Object> schemaConfig()
473
+ {
474
+ ImmutableList.Builder<Object> builder = new ImmutableList.Builder<>();
475
+ builder.add(ImmutableMap.of("name", "id", "type", "long"));
476
+ builder.add(ImmutableMap.of("name", "account", "type", "long"));
477
+ builder.add(ImmutableMap.of("name", "time", "type", "timestamp", "format", "%Y-%m-%d %H:%M:%S"));
478
+ builder.add(ImmutableMap.of("name", "purchase", "type", "timestamp", "format", "%Y%m%d"));
479
+ builder.add(ImmutableMap.of("name", "flg", "type", "boolean"));
480
+ builder.add(ImmutableMap.of("name", "score", "type", "double"));
481
+ builder.add(ImmutableMap.of("name", "comment", "type", "string"));
482
+ return builder.build();
483
+ }
5
484
  }
@@ -0,0 +1,5 @@
1
+ id,account,time,purchase,flg,score,comment
2
+ 1,32864,2015-01-27 19:23:49,20150127,1,123.45,embulk
3
+ 2,14824,2015-01-27 19:01:23,20150127,0,234,56,embulk
4
+ 3,27559,2015-01-28 02:20:02,20150128,1,678.90,embulk
5
+ 4,11270,2015-01-29 11:54:36,20150129,0,100.00,embulk
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muga Nishizawa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-19 00:00:00.000000000 Z
11
+ date: 2016-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
15
- version_requirements: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '1.0'
20
14
  requirement: !ruby/object:Gem::Requirement
21
15
  requirements:
22
16
  - - '>='
23
17
  - !ruby/object:Gem::Version
24
18
  version: '1.0'
19
+ name: bundler
25
20
  prerelease: false
26
21
  type: :development
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
22
  version_requirements: !ruby/object:Gem::Requirement
30
23
  requirements:
31
24
  - - '>='
32
25
  - !ruby/object:Gem::Version
33
- version: '10.0'
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
34
28
  requirement: !ruby/object:Gem::Requirement
35
29
  requirements:
36
30
  - - '>='
37
31
  - !ruby/object:Gem::Version
38
32
  version: '10.0'
33
+ name: rake
39
34
  prerelease: false
40
35
  type: :development
41
- - !ruby/object:Gem::Dependency
42
- name: test-unit
43
36
  version_requirements: !ruby/object:Gem::Requirement
44
37
  requirements:
45
- - - ~>
38
+ - - '>='
46
39
  - !ruby/object:Gem::Version
47
- version: 3.0.2
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
48
42
  requirement: !ruby/object:Gem::Requirement
49
43
  requirements:
50
44
  - - ~>
51
45
  - !ruby/object:Gem::Version
52
46
  version: 3.0.2
47
+ name: test-unit
53
48
  prerelease: false
54
49
  type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 3.0.2
55
55
  description: Elasticsearch output plugin is an Embulk plugin that loads records to Elasticsearch read by any input plugins. Search the input plugins by "embulk-input" keyword.
56
56
  email:
57
57
  - muga.nishizawa@gmail.com
@@ -60,6 +60,7 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - .gitignore
63
+ - CHANGELOG.md
63
64
  - README.md
64
65
  - build.gradle
65
66
  - gradle/wrapper/gradle-wrapper.jar
@@ -70,24 +71,35 @@ files:
70
71
  - settings.gradle
71
72
  - src/main/java/org/embulk/output/elasticsearch/ElasticsearchOutputPlugin.java
72
73
  - src/test/java/org/embulk/output/elasticsearch/TestElasticsearchOutputPlugin.java
73
- - classpath/antlr-runtime-3.5.jar
74
- - classpath/asm-4.1.jar
75
- - classpath/asm-commons-4.1.jar
76
- - classpath/elasticsearch-1.5.2.jar
77
- - classpath/embulk-output-elasticsearch-0.1.8.jar
78
- - classpath/lucene-analyzers-common-4.10.4.jar
79
- - classpath/lucene-core-4.10.4.jar
80
- - classpath/lucene-grouping-4.10.4.jar
81
- - classpath/lucene-highlighter-4.10.4.jar
82
- - classpath/lucene-join-4.10.4.jar
83
- - classpath/lucene-memory-4.10.4.jar
84
- - classpath/lucene-misc-4.10.4.jar
85
- - classpath/lucene-queries-4.10.4.jar
86
- - classpath/lucene-queryparser-4.10.4.jar
87
- - classpath/lucene-sandbox-4.10.4.jar
88
- - classpath/lucene-spatial-4.10.4.jar
89
- - classpath/lucene-suggest-4.10.4.jar
74
+ - src/test/resources/sample_01.csv
75
+ - classpath/commons-cli-1.3.1.jar
76
+ - classpath/compress-lzf-1.0.2.jar
77
+ - classpath/elasticsearch-2.0.0.jar
78
+ - classpath/embulk-output-elasticsearch-0.2.0.jar
79
+ - classpath/HdrHistogram-2.1.6.jar
80
+ - classpath/hppc-0.7.1.jar
81
+ - classpath/jackson-dataformat-cbor-2.5.3.jar
82
+ - classpath/jackson-dataformat-smile-2.5.3.jar
83
+ - classpath/jackson-dataformat-yaml-2.5.3.jar
84
+ - classpath/joda-convert-1.2.jar
85
+ - classpath/joda-time-2.8.2.jar
86
+ - classpath/jsr166e-1.1.0.jar
87
+ - classpath/lucene-analyzers-common-5.2.1.jar
88
+ - classpath/lucene-backward-codecs-5.2.1.jar
89
+ - classpath/lucene-core-5.2.1.jar
90
+ - classpath/lucene-grouping-5.2.1.jar
91
+ - classpath/lucene-highlighter-5.2.1.jar
92
+ - classpath/lucene-join-5.2.1.jar
93
+ - classpath/lucene-memory-5.2.1.jar
94
+ - classpath/lucene-misc-5.2.1.jar
95
+ - classpath/lucene-queries-5.2.1.jar
96
+ - classpath/lucene-queryparser-5.2.1.jar
97
+ - classpath/lucene-sandbox-5.2.1.jar
98
+ - classpath/lucene-spatial-5.2.1.jar
99
+ - classpath/lucene-suggest-5.2.1.jar
100
+ - classpath/netty-3.10.5.Final.jar
90
101
  - classpath/spatial4j-0.4.1.jar
102
+ - classpath/t-digest-3.0.jar
91
103
  homepage: https://github.com/muga/embulk-output-elasticsearch
92
104
  licenses:
93
105
  - Apache 2.0