embulk-input-dynamodb 0.0.1 → 0.0.2
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 +4 -4
- data/LICENSE +1 -1
- data/README.md +13 -3
- data/build.gradle +1 -1
- data/src/main/scala/org/embulk/input/DynamoDBUtil.scala +53 -7
- data/src/main/scala/org/embulk/input/Filter.scala +32 -0
- data/src/main/scala/org/embulk/input/FilterConfig.scala +55 -0
- data/src/main/scala/org/embulk/input/PluginTask.scala +13 -0
- metadata +5 -4
- data/LICENSE.txt +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b499a6aa99576c0713943f0be90e2435b12ac017
|
4
|
+
data.tar.gz: ebfbba02b9e38d42c97049c7742d4245a0f368f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 220cdcde6ec63897c87a53b8cd656a1e2628e930410f8a7dca9873bf2d9ded244222ed867997282804a327f047c46eb51b9d7e0abf16666e96ebf6b1588ac149
|
7
|
+
data.tar.gz: 5d951db675c6166da1b70b65d9d80584eadf0e0aaeb28d710a07741dd4a401955b80eef88619a124739d328a32b8d3b5328228be59b4c06970f871f1060659e1
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -9,16 +9,20 @@
|
|
9
9
|
|
10
10
|
|
11
11
|
## Configuration
|
12
|
-
|
12
|
+
- **access_key**: AWS access key (string, optional)
|
13
|
+
- **secret_key**: AWS secret key (string, optional)
|
14
|
+
If you don't specify keys, I'll use the profile configuration file for the default profile.
|
13
15
|
- **region**: Region Name (string, default: ap-northeast-1)
|
14
|
-
- **table**: Table Name (string, required
|
15
|
-
- **limit
|
16
|
+
- **table**: Table Name (string, required)
|
17
|
+
- **limit**: Scan Limit (integer, default: 100)
|
16
18
|
|
17
19
|
## Example
|
18
20
|
|
19
21
|
```yaml
|
20
22
|
in:
|
21
23
|
type: dynamodb
|
24
|
+
access_key: YOUR_ACCESS_KEY
|
25
|
+
secret_key: YOUR_SECRET_KEY
|
22
26
|
region: ap-northeast-1
|
23
27
|
table: YOUR_TABLE_NAME
|
24
28
|
limit: 1000
|
@@ -27,6 +31,12 @@ in:
|
|
27
31
|
- {name: ColumnB, type: double}
|
28
32
|
- {name: ColumnC, type: string}
|
29
33
|
- {name: ColumnD, type: boolean}
|
34
|
+
filters:
|
35
|
+
- {name: ColumnA, type: long, condition: BETWEEN, value: 10000, value2: 20000}
|
36
|
+
- {name: ColumnC, type: string, condition: EQ, value: foobar}
|
37
|
+
|
38
|
+
out:
|
39
|
+
type: stdout
|
30
40
|
```
|
31
41
|
|
32
42
|
## Build
|
data/build.gradle
CHANGED
@@ -1,43 +1,60 @@
|
|
1
1
|
package org.embulk.input
|
2
2
|
|
3
3
|
import com.amazonaws.ClientConfiguration
|
4
|
+
import com.amazonaws.auth.{AWSCredentials, BasicAWSCredentials, AWSCredentialsProvider}
|
4
5
|
import com.amazonaws.auth.profile.ProfileCredentialsProvider
|
5
6
|
import com.amazonaws.regions.Regions
|
6
7
|
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient
|
7
|
-
import com.amazonaws.services.dynamodbv2.model.
|
8
|
+
import com.amazonaws.services.dynamodbv2.model._
|
8
9
|
import org.embulk.spi._
|
9
10
|
|
10
11
|
import java.util.{ArrayList => JArrayList, List => JList}
|
11
12
|
import scala.collection.JavaConversions._
|
12
13
|
|
13
14
|
object DynamoDBUtil {
|
15
|
+
private def getCredentialsProvider(task: PluginTask): AWSCredentialsProvider = {
|
16
|
+
{for {
|
17
|
+
accessKey <- Option(task.getAccessKey.orNull)
|
18
|
+
secretKey <- Option(task.getSecretKey.orNull)
|
19
|
+
} yield {
|
20
|
+
new AWSCredentialsProvider {
|
21
|
+
override def refresh(): Unit = { }
|
22
|
+
override def getCredentials: AWSCredentials = {
|
23
|
+
new BasicAWSCredentials(accessKey, secretKey)
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}}.getOrElse{
|
27
|
+
new ProfileCredentialsProvider()
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
14
31
|
def createClient(task: PluginTask): AmazonDynamoDBClient = {
|
32
|
+
val credentialsProvider: AWSCredentialsProvider = getCredentialsProvider(task)
|
15
33
|
val client: AmazonDynamoDBClient = new AmazonDynamoDBClient(
|
16
|
-
|
34
|
+
credentialsProvider,
|
17
35
|
new ClientConfiguration().withMaxConnections(10))
|
18
36
|
.withRegion(Regions.fromName(task.getRegion))
|
19
37
|
|
20
38
|
client
|
21
39
|
}
|
22
40
|
|
23
|
-
def listTables(client: AmazonDynamoDBClient): JList[String] = {
|
24
|
-
val result: ListTablesResult = client.listTables()
|
25
|
-
result.getTableNames
|
26
|
-
}
|
27
41
|
|
28
42
|
def scan(client: AmazonDynamoDBClient, task: PluginTask, schema: Schema, output: PageOutput): Unit = {
|
29
43
|
val allocator: BufferAllocator = task.getBufferAllocator
|
30
44
|
val pageBuilder: PageBuilder = new PageBuilder(allocator, schema, output)
|
31
45
|
|
32
|
-
val limit: Int = task.getLimit
|
33
46
|
val attributes: JList[String] = new JArrayList[String]()
|
47
|
+
|
34
48
|
schema.getColumns.foreach { column =>
|
35
49
|
attributes.add(column.getName)
|
36
50
|
}
|
51
|
+
val scanFilter: Map[String, Condition] = createScanFilter(task)
|
52
|
+
val limit: Int = task.getLimit
|
37
53
|
|
38
54
|
val request: ScanRequest = new ScanRequest()
|
39
55
|
.withTableName(task.getTable)
|
40
56
|
.withAttributesToGet(attributes)
|
57
|
+
.withScanFilter(scanFilter)
|
41
58
|
.withLimit(limit)
|
42
59
|
|
43
60
|
val result: ScanResult = client.scan(request)
|
@@ -61,4 +78,33 @@ object DynamoDBUtil {
|
|
61
78
|
|
62
79
|
pageBuilder.finish()
|
63
80
|
}
|
81
|
+
|
82
|
+
private def createScanFilter(task: PluginTask): Map[String, Condition] = {
|
83
|
+
val filterMap = collection.mutable.HashMap[String, Condition]()
|
84
|
+
|
85
|
+
Option(task.getFilters.orNull).map { filters =>
|
86
|
+
filters.getFilters.map { filter =>
|
87
|
+
val attributeValueList = collection.mutable.ArrayBuffer[AttributeValue]()
|
88
|
+
attributeValueList += createAttrinuteValue(filter.getType, filter.getValue)
|
89
|
+
Option(filter.getValue2).map { value2 => attributeValueList += createAttrinuteValue(filter.getType, value2) }
|
90
|
+
|
91
|
+
filterMap += filter.getName -> new Condition()
|
92
|
+
.withComparisonOperator(filter.getCondition)
|
93
|
+
.withAttributeValueList(attributeValueList)
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
filterMap.toMap
|
98
|
+
}
|
99
|
+
|
100
|
+
private def createAttrinuteValue(t: String, v: String): AttributeValue = {
|
101
|
+
t match {
|
102
|
+
case "string" =>
|
103
|
+
new AttributeValue().withS(v)
|
104
|
+
case "long" | "double" =>
|
105
|
+
new AttributeValue().withN(v)
|
106
|
+
case "boolean" =>
|
107
|
+
new AttributeValue().withBOOL(v.toBoolean)
|
108
|
+
}
|
109
|
+
}
|
64
110
|
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
package org.embulk.input
|
2
|
+
|
3
|
+
import java.util.{List => JList}
|
4
|
+
|
5
|
+
import com.fasterxml.jackson.annotation.{JsonValue, JsonCreator}
|
6
|
+
import com.google.common.base.Objects
|
7
|
+
|
8
|
+
class Filter {
|
9
|
+
private var filters: JList[FilterConfig] = _
|
10
|
+
|
11
|
+
@JsonCreator
|
12
|
+
def this(filters: JList[FilterConfig]) {
|
13
|
+
this()
|
14
|
+
this.filters = filters
|
15
|
+
}
|
16
|
+
|
17
|
+
@JsonValue
|
18
|
+
def getFilters: JList[FilterConfig] = filters
|
19
|
+
|
20
|
+
override def equals(obj: Any): Boolean = {
|
21
|
+
if(this == obj) return true
|
22
|
+
|
23
|
+
if(!obj.isInstanceOf[Filter]) return false
|
24
|
+
|
25
|
+
val other: Filter = obj.asInstanceOf[Filter]
|
26
|
+
Objects.equal(filters, other.filters)
|
27
|
+
}
|
28
|
+
|
29
|
+
override def hashCode: Int = {
|
30
|
+
Objects.hashCode(filters)
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
package org.embulk.input
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.annotation.JsonProperty
|
4
|
+
import com.google.common.base.Objects
|
5
|
+
|
6
|
+
class FilterConfig {
|
7
|
+
private var _name: String = _
|
8
|
+
private var _type: String = _
|
9
|
+
private var _condition: String = _
|
10
|
+
private var _value: String = _
|
11
|
+
private var _value2: String = _
|
12
|
+
|
13
|
+
def this(
|
14
|
+
@JsonProperty("name") _name: String,
|
15
|
+
@JsonProperty("type") _type: String,
|
16
|
+
@JsonProperty("condition") _condition: String,
|
17
|
+
@JsonProperty("value") _value: String,
|
18
|
+
@JsonProperty("value2") _value2: String)
|
19
|
+
{
|
20
|
+
this()
|
21
|
+
this._name = _name
|
22
|
+
this._type = _type
|
23
|
+
this._condition = _condition
|
24
|
+
this._value = _value
|
25
|
+
this._value2 = _value2
|
26
|
+
}
|
27
|
+
|
28
|
+
@JsonProperty("name")
|
29
|
+
def getName = _name
|
30
|
+
|
31
|
+
@JsonProperty("type")
|
32
|
+
def getType = _type
|
33
|
+
|
34
|
+
@JsonProperty("condition")
|
35
|
+
def getCondition = _condition
|
36
|
+
|
37
|
+
@JsonProperty("value")
|
38
|
+
def getValue = _value
|
39
|
+
|
40
|
+
@JsonProperty("value2")
|
41
|
+
def getValue2 = _value2
|
42
|
+
|
43
|
+
override def equals(obj: Any): Boolean = {
|
44
|
+
if(this == obj) return true
|
45
|
+
|
46
|
+
if(!obj.isInstanceOf[FilterConfig]) return false
|
47
|
+
|
48
|
+
val other: FilterConfig = obj.asInstanceOf[FilterConfig]
|
49
|
+
Objects.equal(this._name, other._name) &&
|
50
|
+
Objects.equal(this._type, other._type) &&
|
51
|
+
Objects.equal(this._condition, other._condition) &&
|
52
|
+
Objects.equal(this._value, other._value) &&
|
53
|
+
Objects.equal(this._value2, other._value2)
|
54
|
+
}
|
55
|
+
}
|
@@ -1,9 +1,18 @@
|
|
1
1
|
package org.embulk.input
|
2
2
|
|
3
|
+
import com.google.common.base.Optional
|
3
4
|
import org.embulk.config.{ConfigInject, ConfigDefault, Config, Task}
|
4
5
|
import org.embulk.spi.{BufferAllocator, SchemaConfig}
|
5
6
|
|
6
7
|
trait PluginTask extends Task {
|
8
|
+
@Config("access_key")
|
9
|
+
@ConfigDefault("null")
|
10
|
+
def getAccessKey: Optional[String]
|
11
|
+
|
12
|
+
@Config("secret_key")
|
13
|
+
@ConfigDefault("null")
|
14
|
+
def getSecretKey: Optional[String]
|
15
|
+
|
7
16
|
@Config("region")
|
8
17
|
@ConfigDefault("ap-northeast-1")
|
9
18
|
def getRegion: String
|
@@ -18,6 +27,10 @@ trait PluginTask extends Task {
|
|
18
27
|
@Config("columns")
|
19
28
|
def getColumns: SchemaConfig
|
20
29
|
|
30
|
+
@Config("filters")
|
31
|
+
@ConfigDefault("null")
|
32
|
+
def getFilters: Optional[Filter]
|
33
|
+
|
21
34
|
@ConfigInject
|
22
35
|
def getBufferAllocator: BufferAllocator
|
23
36
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-dynamodb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daisuke Higashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -47,7 +47,6 @@ extra_rdoc_files: []
|
|
47
47
|
files:
|
48
48
|
- .gitignore
|
49
49
|
- LICENSE
|
50
|
-
- LICENSE.txt
|
51
50
|
- README.md
|
52
51
|
- build.gradle
|
53
52
|
- gradle/wrapper/gradle-wrapper.jar
|
@@ -57,6 +56,8 @@ files:
|
|
57
56
|
- lib/embulk/input/dynamodb.rb
|
58
57
|
- src/main/scala/org/embulk/input/DynamoDBUtil.scala
|
59
58
|
- src/main/scala/org/embulk/input/DynamodbInputPlugin.scala
|
59
|
+
- src/main/scala/org/embulk/input/Filter.scala
|
60
|
+
- src/main/scala/org/embulk/input/FilterConfig.scala
|
60
61
|
- src/main/scala/org/embulk/input/PluginTask.scala
|
61
62
|
- classpath/aws-java-sdk-core-1.9.22.jar
|
62
63
|
- classpath/aws-java-sdk-dynamodb-1.9.22.jar
|
@@ -64,7 +65,7 @@ files:
|
|
64
65
|
- classpath/aws-java-sdk-s3-1.9.22.jar
|
65
66
|
- classpath/commons-codec-1.6.jar
|
66
67
|
- classpath/commons-logging-1.1.3.jar
|
67
|
-
- classpath/embulk-input-dynamodb-0.0.
|
68
|
+
- classpath/embulk-input-dynamodb-0.0.2.jar
|
68
69
|
- classpath/httpclient-4.3.4.jar
|
69
70
|
- classpath/httpcore-4.3.2.jar
|
70
71
|
- classpath/scala-library-2.11.5.jar
|
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
|
2
|
-
MIT License
|
3
|
-
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
a copy of this software and associated documentation files (the
|
6
|
-
"Software"), to deal in the Software without restriction, including
|
7
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be
|
13
|
-
included in all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|