embulk-input-dynamodb 0.1.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb06f7f31e946edcde0e6fde44443d11c20b2f1b
4
- data.tar.gz: 83f448ad04d7f262c9a1438c79091ce1c6ac2765
3
+ metadata.gz: 603d3c6513d86bf773182a8214d70cb668fcf2a6
4
+ data.tar.gz: 60d9256bb5fac99e56f5424997037323e98f3868
5
5
  SHA512:
6
- metadata.gz: 00544333da3be446d2e479fe1055f5599ea50655f0ba77d6ba465b0d4a0b58316675ac269a0299aaddd8469599b6d43dc02f05fb9b2d07b5daa25d68b4448f9f
7
- data.tar.gz: 8960d06019a11c3e291f7724b0404e9dbd44df041a91cbe4bdaccb9b2e430a5213d60ff597aafab99ff9d6daa3409bead9b634126fa59a2712338e3084c6f318
6
+ metadata.gz: 55d4bdb5960bdf069804360dd0ca9b627bb7cfab0be6bb92c1012b14335019f3c1fd9dd31548fcf9b11b3e22d207efc35b8faf1172b7a5be531d62d39966d61e
7
+ data.tar.gz: 9ae148915f273eca767e740b0cd523f7d355b6f793644106320b592695124682769c47df41b643139d91111d9e541b65e692a32d31b9072a04ea1721b1fd5b35
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
  ## Configuration
12
- - **auth_method**: AWS Credential Type.
12
+ - **auth_method**: AWS Credential Type.
13
13
  Available values options are: `basic`, `env`, `instance`, `profile`, `properties`
14
14
  - **basic**: AWS access key and secret access key
15
15
  - **env**: Environment variables
@@ -21,13 +21,15 @@ Available values options are: `basic`, `env`, `instance`, `profile`, `properties
21
21
  - **secret_key**: AWS secret key (string, required)
22
22
  - If **auth_method** is set `profile`
23
23
  - **profile_name**: The name of a local configuration profile (string, optional)
24
- - **region**: Region Name (string, default: ap-northeast-1)
24
+ - **region**: Region Name (string, optional)
25
+ - **end_point**: EndPoint URL (string, optional)
26
+ `end_point` has priority when `region` and `end_point` are specified.
25
27
  - **table**: Table Name (string, required)
26
28
  - **scan_limit**: DynamoDB 1time Scan Query size limit (Int, optional)
27
29
  - **record_limit**: Max Record Search limit (Long, optional)
28
30
  - **columns**: a key-value pairs where key is a column name and value is options for the column (required)
29
31
  - **name**: Column name.
30
- - **type**: Column values are converted to this embulk type.
32
+ - **type**: Column values are converted to this embulk type.
31
33
  Available values options are: `boolean`, `long`, `double`, `string`, `json`
32
34
  - **filters**: query filter (optional)
33
35
 
@@ -46,7 +48,7 @@ in:
46
48
  - {name: ColumnB, type: double}
47
49
  - {name: ColumnC, type: string}
48
50
  - {name: ColumnD, type: boolean}
49
- - {name: ColumnE, type: json}
51
+ - {name: ColumnE, type: json} # DynamoDB Map, List and Set Column Type are json.
50
52
  filters:
51
53
  - {name: ColumnA, type: long, condition: BETWEEN, value: 10000, value2: 20000}
52
54
  - {name: ColumnC, type: string, condition: EQ, value: foobar}
@@ -55,6 +57,13 @@ out:
55
57
  type: stdout
56
58
  ```
57
59
 
60
+ ## Try
61
+
62
+ ```
63
+ $ ./gradlew classpath
64
+ $ embulk preview -I lib your-sample.yml
65
+ ```
66
+
58
67
  ## Build
59
68
 
60
69
  ```
data/build.gradle CHANGED
@@ -14,7 +14,7 @@ configurations {
14
14
  provided
15
15
  }
16
16
 
17
- version = "0.1.0"
17
+ version = "0.1.1"
18
18
 
19
19
  sourceCompatibility = 1.7
20
20
  targetCompatibility = 1.7
data/circle.yml CHANGED
@@ -1,8 +1,16 @@
1
+ machine:
2
+ services:
3
+ - docker
4
+
1
5
  general:
2
6
  artifacts:
3
7
  - "~/embulk-input-dynamodb/build/reports/tests"
4
8
 
5
9
  test:
10
+ pre:
11
+ - sh ./test/run_dynamodb_local.sh; sleep 2
12
+ - sh ./test/create_table.sh
13
+ - sh ./test/put_items.sh
6
14
  post:
7
- - mkdir -p $CIRCLE_TEST_REPORTS/junit/
8
- - find . -type f -regex ".*/test-results/*/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
15
+ - mkdir -p $CIRCLE_TEST_REPORTS/junit/
16
+ - find . -type f -regex ".*/test-results/*/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
@@ -60,12 +60,4 @@ object AwsCredentials {
60
60
  }
61
61
  }
62
62
  }
63
-
64
- private def require[A](value: Optional[A], message: String): A = {
65
- if (value.isPresent) {
66
- value.get()
67
- } else {
68
- throw new ConfigException("Required option is not set: " + message)
69
- }
70
- }
71
63
  }
@@ -6,20 +6,27 @@ import com.amazonaws.ClientConfiguration
6
6
  import com.amazonaws.regions.Regions
7
7
  import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient
8
8
  import com.amazonaws.services.dynamodbv2.model.{AttributeValue, Condition, ScanRequest, ScanResult}
9
+ import org.embulk.config.ConfigException
9
10
  import org.embulk.spi._
10
11
  import org.embulk.spi.`type`.Types
11
- import org.msgpack.value.{ValueFactory, Value}
12
+ import org.msgpack.value.{Value, ValueFactory}
12
13
 
13
- import scala.collection.JavaConversions._
14
14
  import scala.collection.JavaConverters._
15
15
 
16
16
  object DynamoDBUtil {
17
17
  def createClient(task: PluginTask): AmazonDynamoDBClient = {
18
- new AmazonDynamoDBClient(
18
+ val client = new AmazonDynamoDBClient(
19
19
  AwsCredentials.getCredentialsProvider(task),
20
20
  new ClientConfiguration()
21
21
  .withMaxConnections(50)) // SDK Default Value
22
- .withRegion(Regions.fromName(task.getRegion))
22
+
23
+ if (task.getEndPoint.isPresent) {
24
+ client.withEndpoint(task.getEndPoint.get())
25
+ } else if (task.getRegion.isPresent) {
26
+ client.withRegion(Regions.fromName(task.getRegion.get()))
27
+ } else {
28
+ throw new ConfigException("At least one of EndPoint or Region must be set")
29
+ }
23
30
  }
24
31
 
25
32
 
@@ -34,10 +41,10 @@ object DynamoDBUtil {
34
41
 
35
42
  val attributes: JList[String] = new JArrayList[String]()
36
43
 
37
- schema.getColumns.foreach { column =>
44
+ schema.getColumns.asScala.foreach { column =>
38
45
  attributes.add(column.getName)
39
46
  }
40
- val scanFilter: JMap[String, Condition] = createScanFilter(task)
47
+ val scanFilter: JMap[String, Condition] = createScanFilter(task).asJava
41
48
  var evaluateKey: JMap[String, AttributeValue] = null
42
49
 
43
50
  val scanLimit: Long = task.getScanLimit
@@ -60,8 +67,8 @@ object DynamoDBUtil {
60
67
  val result: ScanResult = client.scan(request)
61
68
  evaluateKey = result.getLastEvaluatedKey
62
69
 
63
- result.getItems.foreach { item =>
64
- schema.getColumns.foreach { column =>
70
+ result.getItems.asScala.foreach { item =>
71
+ schema.getColumns.asScala.foreach { column =>
65
72
  val value = item.asScala.get(column.getName)
66
73
  column.getType match {
67
74
  case Types.STRING =>
@@ -97,7 +104,7 @@ object DynamoDBUtil {
97
104
  val filterMap = collection.mutable.HashMap[String, Condition]()
98
105
 
99
106
  Option(task.getFilters.orNull).map { filters =>
100
- filters.getFilters.map { filter =>
107
+ filters.getFilters.asScala.map { filter =>
101
108
  val attributeValueList = collection.mutable.ArrayBuffer[AttributeValue]()
102
109
  attributeValueList += createAttributeValue(filter.getType, filter.getValue)
103
110
  Option(filter.getValue2).map { value2 =>
@@ -105,7 +112,7 @@ object DynamoDBUtil {
105
112
 
106
113
  filterMap += filter.getName -> new Condition()
107
114
  .withComparisonOperator(filter.getCondition)
108
- .withAttributeValueList(attributeValueList)
115
+ .withAttributeValueList(attributeValueList.asJava)
109
116
  }
110
117
  }
111
118
 
@@ -138,7 +145,7 @@ object DynamoDBUtil {
138
145
  value.map(_.getN.toDouble).getOrElse(0D)
139
146
 
140
147
  implicit private def BooleanConvert(value: Option[AttributeValue]): Boolean =
141
- value.exists(_.getS.toBoolean)
148
+ value.exists(_.getBOOL)
142
149
 
143
150
  implicit private def JsonConvert(value: Option[AttributeValue]): Value = {
144
151
  value.map { attr =>
@@ -22,8 +22,12 @@ trait PluginTask extends Task {
22
22
  def getProfileName: Optional[String]
23
23
 
24
24
  @Config("region")
25
- @ConfigDefault("ap-northeast-1")
26
- def getRegion: String
25
+ @ConfigDefault("null")
26
+ def getRegion: Optional[String]
27
+
28
+ @Config("end_point")
29
+ @ConfigDefault("null")
30
+ def getEndPoint: Optional[String]
27
31
 
28
32
  @Config("scan_limit")
29
33
  @ConfigDefault("0")
@@ -0,0 +1,14 @@
1
+ package org.embulk.input
2
+
3
+ import com.google.common.base.Optional
4
+ import org.embulk.config.ConfigException
5
+
6
+ package object dynamodb {
7
+ def require[A](value: Optional[A], message: String): A = {
8
+ if (value.isPresent) {
9
+ value.get()
10
+ } else {
11
+ throw new ConfigException("Required option is not set: " + message)
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,23 @@
1
+ in:
2
+ type: dynamodb
3
+ end_point: http://localhost:8000/
4
+ table: ENV_VAR
5
+ auth_method: basic
6
+ access_key: dummy
7
+ secret_key: dummy
8
+ columns:
9
+ - {name: pri-key, type: string}
10
+ - {name: sort-key, type: long}
11
+ - {name: doubleValue, type: double}
12
+ - {name: boolValue, type: boolean}
13
+ - {name: listValue, type: json}
14
+ - {name: mapValue, type: json}
15
+
16
+ out:
17
+ type: file
18
+ path_prefix: dynamodb-local-result
19
+ file_ext: tsv
20
+ formatter:
21
+ type: csv
22
+ delimiter: "\t"
23
+ header_line: false
@@ -138,12 +138,18 @@ class AttributeValueHelperTest {
138
138
  }
139
139
 
140
140
  def attr[A](value: A)(implicit f: A=> AttributeValue): AttributeValue = f(value)
141
- implicit def StringAttributeValue(value: String): AttributeValue = new AttributeValue().withS(value)
142
- implicit def IntegerAttributeValue(value: Int): AttributeValue = new AttributeValue().withN(value.toString)
143
- implicit def LongAttributeValue(value: Long): AttributeValue = new AttributeValue().withN(value.toString)
144
- implicit def FloatAttributeValue(value: Float): AttributeValue = new AttributeValue().withN(value.toString)
145
- implicit def DoubleAttributeValue(value: Double): AttributeValue = new AttributeValue().withN(value.toString)
146
- implicit def BooleanAttributeValue(value: Boolean): AttributeValue = new AttributeValue().withBOOL(value)
141
+ implicit def StringAttributeValue(value: String): AttributeValue
142
+ = new AttributeValue().withS(value)
143
+ implicit def IntegerAttributeValue(value: Int): AttributeValue
144
+ = new AttributeValue().withN(value.toString)
145
+ implicit def LongAttributeValue(value: Long): AttributeValue
146
+ = new AttributeValue().withN(value.toString)
147
+ implicit def FloatAttributeValue(value: Float): AttributeValue
148
+ = new AttributeValue().withN(value.toString)
149
+ implicit def DoubleAttributeValue(value: Double): AttributeValue
150
+ = new AttributeValue().withN(value.toString)
151
+ implicit def BooleanAttributeValue(value: Boolean): AttributeValue
152
+ = new AttributeValue().withBOOL(value)
147
153
  implicit def MapAttributeValue(value: Map[String, AttributeValue]): AttributeValue
148
154
  = new AttributeValue().withM(value.asJava)
149
155
  implicit def ListAttributeValue(value: List[AttributeValue]): AttributeValue
@@ -0,0 +1,81 @@
1
+ package org.embulk.input.dynamodb
2
+
3
+ import java.io.File
4
+ import java.nio.charset.Charset
5
+ import java.nio.file.{FileSystems, Files}
6
+
7
+ import com.fasterxml.jackson.databind.ObjectMapper
8
+ import com.google.inject.{Binder, Module}
9
+ import org.embulk.EmbulkEmbed
10
+ import org.embulk.config.ConfigSource
11
+ import org.embulk.plugin.InjectedPluginSource
12
+ import org.embulk.spi.InputPlugin
13
+ import org.hamcrest.CoreMatchers._
14
+ import org.junit.Assert._
15
+ import org.junit.{Before, Test}
16
+
17
+ class DynamoDBUtilTest {
18
+ private var embulk: EmbulkEmbed = null
19
+
20
+ private var EMBULK_DYNAMODB_TEST_TABLE: String = null
21
+ private var mapper: ObjectMapper = null
22
+
23
+ @Before
24
+ def createResources() {
25
+ // Get Environments
26
+ EMBULK_DYNAMODB_TEST_TABLE = System.getenv("EMBULK_DYNAMODB_TEST_TABLE")
27
+
28
+ val bootstrap = new EmbulkEmbed.Bootstrap()
29
+ bootstrap.addModules(new Module {
30
+ def configure(binder: Binder): Unit = {
31
+ InjectedPluginSource.registerPluginTo(binder,
32
+ classOf[InputPlugin],
33
+ "dynamodb",
34
+ classOf[DynamodbInputPlugin])
35
+ }
36
+ })
37
+
38
+ embulk = bootstrap.initializeCloseable()
39
+
40
+ mapper = new ObjectMapper()
41
+ }
42
+
43
+
44
+ def doTest(config: ConfigSource) {
45
+ embulk.run(config)
46
+
47
+ val fs = FileSystems.getDefault
48
+ val lines = Files.readAllLines(fs.getPath("dynamodb-local-result000.00.tsv"), Charset.forName("UTF-8"))
49
+ assertEquals(lines.size, 1)
50
+
51
+ val head = lines.get(0)
52
+ val values = head.split("\t")
53
+
54
+ assertThat(values(0), is("key-1"))
55
+ assertThat(values(1), is("0"))
56
+ assertThat(values(2), is("42.195"))
57
+ assertThat(values(3), is("true"))
58
+
59
+ val listValue = mapper.readValue(values(4).replaceAll("\"(?!\")", ""), classOf[java.util.List[Object]])
60
+ assertThat(listValue.size(), is(2))
61
+ assertThat(listValue.get(0).asInstanceOf[String], is("list-value"))
62
+ assertThat(listValue.get(1).asInstanceOf[Int], is(123))
63
+
64
+ val mapValue = mapper.readValue(values(5).replaceAll("\"(?!\")", ""), classOf[java.util.Map[String, Object]])
65
+ assert(mapValue.containsKey("map-key-1"))
66
+ assertThat(mapValue.get("map-key-1").asInstanceOf[String], is("map-value-1"))
67
+ assert(mapValue.containsKey("map-key-2"))
68
+ assertThat(mapValue.get("map-key-2").asInstanceOf[Int], is(456))
69
+ }
70
+
71
+ @Test
72
+ def scanTest() {
73
+ val config = embulk.newConfigLoader().fromYamlFile(
74
+ new File("src/test/resources/yaml/dynamodb-local.yml"))
75
+
76
+ config.getNested("in")
77
+ .set("table", EMBULK_DYNAMODB_TEST_TABLE)
78
+
79
+ doTest(config)
80
+ }
81
+ }
@@ -0,0 +1,16 @@
1
+ #!/bin/sh
2
+
3
+ aws dynamodb create-table \
4
+ --table-name='EMBULK_DYNAMODB_TEST_TABLE' \
5
+ --attribute-definitions='[
6
+ {"AttributeName":"pri-key","AttributeType":"S"},
7
+ {"AttributeName":"sort-key","AttributeType":"N"}
8
+ ]' \
9
+ --key-schema='[
10
+ {"AttributeName":"pri-key","KeyType":"HASH"},
11
+ {"AttributeName":"sort-key","KeyType":"RANGE"}
12
+ ]' \
13
+ --provisioned-throughput='{"ReadCapacityUnits":5, "WriteCapacityUnits":5}' \
14
+ --endpoint-url http://localhost:8000 \
15
+ --region us-east-1
16
+
data/test/put_items.sh ADDED
@@ -0,0 +1,25 @@
1
+ #!/bin/sh
2
+
3
+ aws dynamodb put-item \
4
+ --table-name='EMBULK_DYNAMODB_TEST_TABLE' \
5
+ --item='{
6
+ "pri-key" : { "S" : "key-1" },
7
+ "sort-key" : { "N" : "0" },
8
+ "doubleValue" : { "N" : "42.195" },
9
+ "boolValue" : { "BOOL" : true },
10
+ "listValue" : { "L":
11
+ [
12
+ { "S" : "list-value"},
13
+ { "N" : "123"}
14
+ ]
15
+ },
16
+ "mapValue" : { "M":
17
+ {
18
+ "map-key-1" : { "S" : "map-value-1" },
19
+ "map-key-2" : { "N" : "456" }
20
+ }
21
+ }
22
+ }' \
23
+ --endpoint-url http://localhost:8000 \
24
+ --region us-east-1
25
+
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ docker run -d \
4
+ -p 8000:8000 \
5
+ -v $PWD/dynamodb-local:/data \
6
+ --env DYNAMO_OPT='-dbPath /data -sharedDb' \
7
+ lulichn/dynamodb-local
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.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daisuke Higashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-04 00:00:00.000000000 Z
11
+ date: 2016-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -64,25 +64,31 @@ files:
64
64
  - src/main/scala/org/embulk/input/dynamodb/Filter.scala
65
65
  - src/main/scala/org/embulk/input/dynamodb/FilterConfig.scala
66
66
  - src/main/scala/org/embulk/input/dynamodb/PluginTask.scala
67
+ - src/main/scala/org/embulk/input/dynamodb/package.scala
67
68
  - src/test/resources/json/test.json
68
69
  - src/test/resources/json/test.template
69
70
  - src/test/resources/yaml/authMethodBasic.yml
70
71
  - src/test/resources/yaml/authMethodBasic_Error.yml
71
72
  - src/test/resources/yaml/authMethodEnv.yml
72
73
  - src/test/resources/yaml/authMethodProfile.yml
74
+ - src/test/resources/yaml/dynamodb-local.yml
73
75
  - src/test/resources/yaml/notSetAuthMethod.yml
74
76
  - src/test/scala/org/embulk/input/dynamodb/AttributeValueHelperTest.scala
75
77
  - src/test/scala/org/embulk/input/dynamodb/AwsCredentialsTest.scala
76
- - classpath/aws-java-sdk-core-1.10.43.jar
78
+ - src/test/scala/org/embulk/input/dynamodb/DynamoDBUtilTest.scala
79
+ - test/create_table.sh
80
+ - test/put_items.sh
81
+ - test/run_dynamodb_local.sh
82
+ - classpath/commons-logging-1.1.3.jar
83
+ - classpath/commons-codec-1.6.jar
84
+ - classpath/scala-library-2.11.7.jar
77
85
  - classpath/aws-java-sdk-dynamodb-1.10.43.jar
86
+ - classpath/embulk-input-dynamodb-0.1.1.jar
78
87
  - classpath/aws-java-sdk-kms-1.10.43.jar
79
- - classpath/aws-java-sdk-s3-1.10.43.jar
80
- - classpath/commons-codec-1.6.jar
81
- - classpath/commons-logging-1.1.3.jar
82
- - classpath/embulk-input-dynamodb-0.1.0.jar
83
- - classpath/httpclient-4.3.6.jar
84
88
  - classpath/httpcore-4.3.3.jar
85
- - classpath/scala-library-2.11.7.jar
89
+ - classpath/httpclient-4.3.6.jar
90
+ - classpath/aws-java-sdk-core-1.10.43.jar
91
+ - classpath/aws-java-sdk-s3-1.10.43.jar
86
92
  homepage: https://github.com/lulichn/embulk-input-dynamodb
87
93
  licenses:
88
94
  - MIT
@@ -107,4 +113,7 @@ rubygems_version: 2.1.9
107
113
  signing_key:
108
114
  specification_version: 4
109
115
  summary: Dynamodb input plugin for Embulk
110
- test_files: []
116
+ test_files:
117
+ - test/create_table.sh
118
+ - test/put_items.sh
119
+ - test/run_dynamodb_local.sh