embulk-input-dynamodb 0.1.0 → 0.1.1

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: 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