embulk-output-s3_parquet 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +3 -0
- data/.github/workflows/test.yml +2 -0
- data/.scalafmt.conf +5 -0
- data/CHANGELOG.md +15 -0
- data/README.md +3 -2
- data/build.gradle +19 -9
- data/example/config.yml +3 -1
- data/example/prepare_s3_bucket.sh +6 -0
- data/example/with_catalog.yml +3 -1
- data/example/with_logicaltypes.yml +3 -1
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +1 -1
- data/gradlew +31 -20
- data/gradlew.bat +17 -1
- data/run_s3_local.sh +7 -0
- data/src/main/scala/org/embulk/output/s3_parquet/CatalogRegistrator.scala +226 -178
- data/src/main/scala/org/embulk/output/s3_parquet/ContextClassLoaderSwapper.scala +18 -0
- data/src/main/scala/org/embulk/output/s3_parquet/S3ParquetOutputPlugin.scala +293 -204
- data/src/main/scala/org/embulk/output/s3_parquet/S3ParquetPageOutput.scala +46 -49
- data/src/main/scala/org/embulk/output/s3_parquet/aws/Aws.scala +46 -50
- data/src/main/scala/org/embulk/output/s3_parquet/aws/AwsClientConfiguration.scala +18 -23
- data/src/main/scala/org/embulk/output/s3_parquet/aws/AwsCredentials.scala +146 -119
- data/src/main/scala/org/embulk/output/s3_parquet/aws/AwsEndpointConfiguration.scala +32 -35
- data/src/main/scala/org/embulk/output/s3_parquet/aws/AwsS3Configuration.scala +45 -41
- data/src/main/scala/org/embulk/output/s3_parquet/aws/HttpProxy.scala +40 -43
- data/src/main/scala/org/embulk/output/s3_parquet/parquet/EmbulkMessageType.scala +138 -92
- data/src/main/scala/org/embulk/output/s3_parquet/parquet/LogicalTypeHandler.scala +117 -102
- data/src/main/scala/org/embulk/output/s3_parquet/parquet/LogicalTypeHandlerStore.scala +91 -84
- data/src/main/scala/org/embulk/output/s3_parquet/parquet/ParquetFileWriteSupport.scala +30 -29
- data/src/main/scala/org/embulk/output/s3_parquet/parquet/ParquetFileWriter.scala +143 -152
- data/src/test/scala/org/embulk/output/s3_parquet/TestS3ParquetOutputPlugin.scala +144 -117
- data/src/test/scala/org/embulk/output/s3_parquet/parquet/TestLogicalTypeHandler.scala +72 -66
- data/src/test/scala/org/embulk/output/s3_parquet/parquet/TestLogicalTypeHandlerStore.scala +149 -132
- metadata +22 -15
@@ -1,6 +1,5 @@
|
|
1
1
|
package org.embulk.output.s3_parquet
|
2
2
|
|
3
|
-
|
4
3
|
import java.io.File
|
5
4
|
import java.nio.file.{Files, Paths}
|
6
5
|
|
@@ -11,63 +10,61 @@ import org.embulk.config.TaskReport
|
|
11
10
|
import org.embulk.output.s3_parquet.aws.Aws
|
12
11
|
import org.embulk.spi.{Exec, Page, PageReader, TransactionalPageOutput}
|
13
12
|
|
13
|
+
case class S3ParquetPageOutput(
|
14
|
+
outputLocalFile: String,
|
15
|
+
reader: PageReader,
|
16
|
+
writer: ParquetWriter[PageReader],
|
17
|
+
aws: Aws,
|
18
|
+
destBucket: String,
|
19
|
+
destKey: String
|
20
|
+
) extends TransactionalPageOutput {
|
14
21
|
|
15
|
-
|
16
|
-
reader: PageReader,
|
17
|
-
writer: ParquetWriter[PageReader],
|
18
|
-
aws: Aws,
|
19
|
-
destBucket: String,
|
20
|
-
destKey: String)
|
21
|
-
extends TransactionalPageOutput
|
22
|
-
{
|
23
|
-
|
24
|
-
private var isClosed: Boolean = false
|
22
|
+
private var isClosed: Boolean = false
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
writer.write(reader)
|
31
|
-
}
|
24
|
+
override def add(page: Page): Unit = {
|
25
|
+
reader.setPage(page)
|
26
|
+
while (reader.nextRecord()) {
|
27
|
+
writer.write(reader)
|
32
28
|
}
|
29
|
+
}
|
33
30
|
|
34
|
-
|
35
|
-
{
|
36
|
-
}
|
31
|
+
override def finish(): Unit = {}
|
37
32
|
|
38
|
-
|
39
|
-
{
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
isClosed = true
|
44
|
-
}
|
33
|
+
override def close(): Unit = {
|
34
|
+
synchronized {
|
35
|
+
if (!isClosed) {
|
36
|
+
ContextClassLoaderSwapper.usingPluginClass {
|
37
|
+
writer.close()
|
45
38
|
}
|
39
|
+
isClosed = true
|
40
|
+
}
|
46
41
|
}
|
42
|
+
}
|
47
43
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
}
|
44
|
+
override def abort(): Unit = {
|
45
|
+
close()
|
46
|
+
cleanup()
|
47
|
+
}
|
53
48
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
Exec.newTaskReport()
|
63
|
-
.set("bucket", result.getBucketName)
|
64
|
-
.set("key", result.getKey)
|
65
|
-
.set("etag", result.getETag)
|
66
|
-
.set("version_id", result.getVersionId)
|
49
|
+
override def commit(): TaskReport = {
|
50
|
+
close()
|
51
|
+
val result: UploadResult = ContextClassLoaderSwapper.usingPluginClass {
|
52
|
+
aws.withTransferManager { xfer: TransferManager =>
|
53
|
+
val upload: Upload =
|
54
|
+
xfer.upload(destBucket, destKey, new File(outputLocalFile))
|
55
|
+
upload.waitForUploadResult()
|
56
|
+
}
|
67
57
|
}
|
58
|
+
cleanup()
|
59
|
+
Exec
|
60
|
+
.newTaskReport()
|
61
|
+
.set("bucket", result.getBucketName)
|
62
|
+
.set("key", result.getKey)
|
63
|
+
.set("etag", result.getETag)
|
64
|
+
.set("version_id", result.getVersionId)
|
65
|
+
}
|
68
66
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
}
|
67
|
+
private def cleanup(): Unit = {
|
68
|
+
Files.delete(Paths.get(outputLocalFile))
|
69
|
+
}
|
73
70
|
}
|
@@ -1,63 +1,59 @@
|
|
1
1
|
package org.embulk.output.s3_parquet.aws
|
2
2
|
|
3
|
-
|
4
3
|
import com.amazonaws.client.builder.AwsClientBuilder
|
5
4
|
import com.amazonaws.services.glue.{AWSGlue, AWSGlueClientBuilder}
|
6
5
|
import com.amazonaws.services.s3.{AmazonS3, AmazonS3ClientBuilder}
|
7
|
-
import com.amazonaws.services.s3.transfer.{
|
8
|
-
|
9
|
-
|
10
|
-
object Aws
|
11
|
-
{
|
12
|
-
|
13
|
-
trait Task
|
14
|
-
extends AwsCredentials.Task
|
15
|
-
with AwsEndpointConfiguration.Task
|
16
|
-
with AwsClientConfiguration.Task
|
17
|
-
with AwsS3Configuration.Task
|
18
|
-
|
19
|
-
def apply(task: Task): Aws =
|
20
|
-
{
|
21
|
-
new Aws(task)
|
22
|
-
}
|
23
|
-
|
6
|
+
import com.amazonaws.services.s3.transfer.{
|
7
|
+
TransferManager,
|
8
|
+
TransferManagerBuilder
|
24
9
|
}
|
25
10
|
|
26
|
-
|
27
|
-
{
|
28
|
-
|
29
|
-
def withS3[A](f: AmazonS3 => A): A =
|
30
|
-
{
|
31
|
-
val builder: AmazonS3ClientBuilder = AmazonS3ClientBuilder.standard()
|
32
|
-
AwsS3Configuration(task).configureAmazonS3ClientBuilder(builder)
|
33
|
-
val svc = createService(builder)
|
34
|
-
try f(svc)
|
35
|
-
finally svc.shutdown()
|
36
|
-
}
|
11
|
+
object Aws {
|
37
12
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
finally svc.shutdownNow(false)
|
44
|
-
}
|
45
|
-
}
|
13
|
+
trait Task
|
14
|
+
extends AwsCredentials.Task
|
15
|
+
with AwsEndpointConfiguration.Task
|
16
|
+
with AwsClientConfiguration.Task
|
17
|
+
with AwsS3Configuration.Task
|
46
18
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
val svc = createService(builder)
|
51
|
-
try f(svc)
|
52
|
-
finally svc.shutdown()
|
53
|
-
}
|
19
|
+
def apply(task: Task): Aws = {
|
20
|
+
new Aws(task)
|
21
|
+
}
|
54
22
|
|
55
|
-
|
56
|
-
{
|
57
|
-
AwsEndpointConfiguration(task).configureAwsClientBuilder(builder)
|
58
|
-
AwsClientConfiguration(task).configureAwsClientBuilder(builder)
|
59
|
-
builder.setCredentials(AwsCredentials(task).createAwsCredentialsProvider)
|
23
|
+
}
|
60
24
|
|
61
|
-
|
25
|
+
class Aws(task: Aws.Task) {
|
26
|
+
|
27
|
+
def withS3[A](f: AmazonS3 => A): A = {
|
28
|
+
val builder: AmazonS3ClientBuilder = AmazonS3ClientBuilder.standard()
|
29
|
+
AwsS3Configuration(task).configureAmazonS3ClientBuilder(builder)
|
30
|
+
val svc = createService(builder)
|
31
|
+
try f(svc)
|
32
|
+
finally svc.shutdown()
|
33
|
+
}
|
34
|
+
|
35
|
+
def withTransferManager[A](f: TransferManager => A): A = {
|
36
|
+
withS3 { s3 =>
|
37
|
+
val svc = TransferManagerBuilder.standard().withS3Client(s3).build()
|
38
|
+
try f(svc)
|
39
|
+
finally svc.shutdownNow(false)
|
62
40
|
}
|
41
|
+
}
|
42
|
+
|
43
|
+
def withGlue[A](f: AWSGlue => A): A = {
|
44
|
+
val builder: AWSGlueClientBuilder = AWSGlueClientBuilder.standard()
|
45
|
+
val svc = createService(builder)
|
46
|
+
try f(svc)
|
47
|
+
finally svc.shutdown()
|
48
|
+
}
|
49
|
+
|
50
|
+
def createService[S <: AwsClientBuilder[S, T], T](
|
51
|
+
builder: AwsClientBuilder[S, T]
|
52
|
+
): T = {
|
53
|
+
AwsEndpointConfiguration(task).configureAwsClientBuilder(builder)
|
54
|
+
AwsClientConfiguration(task).configureAwsClientBuilder(builder)
|
55
|
+
builder.setCredentials(AwsCredentials(task).createAwsCredentialsProvider)
|
56
|
+
|
57
|
+
builder.build()
|
58
|
+
}
|
63
59
|
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
package org.embulk.output.s3_parquet.aws
|
2
2
|
|
3
|
-
|
4
3
|
import java.util.Optional
|
5
4
|
|
6
5
|
import com.amazonaws.ClientConfiguration
|
@@ -8,35 +7,31 @@ import com.amazonaws.client.builder.AwsClientBuilder
|
|
8
7
|
import org.embulk.config.{Config, ConfigDefault}
|
9
8
|
import org.embulk.output.s3_parquet.aws.AwsClientConfiguration.Task
|
10
9
|
|
10
|
+
object AwsClientConfiguration {
|
11
11
|
|
12
|
-
|
13
|
-
{
|
14
|
-
|
15
|
-
trait Task
|
16
|
-
{
|
12
|
+
trait Task {
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
@Config("http_proxy")
|
15
|
+
@ConfigDefault("null")
|
16
|
+
def getHttpProxy: Optional[HttpProxy.Task]
|
21
17
|
|
22
|
-
|
18
|
+
}
|
23
19
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
20
|
+
def apply(task: Task): AwsClientConfiguration = {
|
21
|
+
new AwsClientConfiguration(task)
|
22
|
+
}
|
28
23
|
}
|
29
24
|
|
30
|
-
class AwsClientConfiguration(task: Task)
|
31
|
-
{
|
25
|
+
class AwsClientConfiguration(task: Task) {
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
27
|
+
def configureAwsClientBuilder[S <: AwsClientBuilder[S, T], T](
|
28
|
+
builder: AwsClientBuilder[S, T]
|
29
|
+
): Unit = {
|
30
|
+
task.getHttpProxy.ifPresent { v =>
|
31
|
+
val cc = new ClientConfiguration
|
32
|
+
HttpProxy(v).configureClientConfiguration(cc)
|
33
|
+
builder.setClientConfiguration(cc)
|
40
34
|
}
|
35
|
+
}
|
41
36
|
|
42
37
|
}
|
@@ -1,147 +1,174 @@
|
|
1
1
|
package org.embulk.output.s3_parquet.aws
|
2
2
|
|
3
|
-
|
4
3
|
import java.util.Optional
|
5
4
|
|
6
|
-
import com.amazonaws.auth.{
|
7
|
-
|
5
|
+
import com.amazonaws.auth.{
|
6
|
+
AnonymousAWSCredentials,
|
7
|
+
AWSCredentialsProvider,
|
8
|
+
AWSStaticCredentialsProvider,
|
9
|
+
BasicAWSCredentials,
|
10
|
+
BasicSessionCredentials,
|
11
|
+
DefaultAWSCredentialsProviderChain,
|
12
|
+
EC2ContainerCredentialsProviderWrapper,
|
13
|
+
EnvironmentVariableCredentialsProvider,
|
14
|
+
STSAssumeRoleSessionCredentialsProvider,
|
15
|
+
SystemPropertiesCredentialsProvider,
|
16
|
+
WebIdentityTokenCredentialsProvider
|
17
|
+
}
|
18
|
+
import com.amazonaws.auth.profile.{
|
19
|
+
ProfileCredentialsProvider,
|
20
|
+
ProfilesConfigFile
|
21
|
+
}
|
8
22
|
import org.embulk.config.{Config, ConfigDefault, ConfigException}
|
9
23
|
import org.embulk.output.s3_parquet.aws.AwsCredentials.Task
|
10
24
|
import org.embulk.spi.unit.LocalFile
|
11
25
|
|
26
|
+
object AwsCredentials {
|
12
27
|
|
13
|
-
|
14
|
-
{
|
28
|
+
trait Task {
|
15
29
|
|
16
|
-
|
17
|
-
|
30
|
+
@Config("auth_method")
|
31
|
+
@ConfigDefault("\"default\"")
|
32
|
+
def getAuthMethod: String
|
18
33
|
|
19
|
-
|
20
|
-
|
21
|
-
|
34
|
+
@Config("access_key_id")
|
35
|
+
@ConfigDefault("null")
|
36
|
+
def getAccessKeyId: Optional[String]
|
22
37
|
|
23
|
-
|
24
|
-
|
25
|
-
|
38
|
+
@Config("secret_access_key")
|
39
|
+
@ConfigDefault("null")
|
40
|
+
def getSecretAccessKey: Optional[String]
|
26
41
|
|
27
|
-
|
28
|
-
|
29
|
-
|
42
|
+
@Config("session_token")
|
43
|
+
@ConfigDefault("null")
|
44
|
+
def getSessionToken: Optional[String]
|
30
45
|
|
31
|
-
|
32
|
-
|
33
|
-
|
46
|
+
@Config("profile_file")
|
47
|
+
@ConfigDefault("null")
|
48
|
+
def getProfileFile: Optional[LocalFile]
|
34
49
|
|
35
|
-
|
36
|
-
|
37
|
-
|
50
|
+
@Config("profile_name")
|
51
|
+
@ConfigDefault("\"default\"")
|
52
|
+
def getProfileName: String
|
38
53
|
|
39
|
-
|
40
|
-
|
41
|
-
|
54
|
+
@Config("role_arn")
|
55
|
+
@ConfigDefault("null")
|
56
|
+
def getRoleArn: Optional[String]
|
42
57
|
|
43
|
-
|
44
|
-
|
45
|
-
|
58
|
+
@Config("role_session_name")
|
59
|
+
@ConfigDefault("null")
|
60
|
+
def getRoleSessionName: Optional[String]
|
46
61
|
|
47
|
-
|
48
|
-
|
49
|
-
|
62
|
+
@Config("role_external_id")
|
63
|
+
@ConfigDefault("null")
|
64
|
+
def getRoleExternalId: Optional[String]
|
50
65
|
|
51
|
-
|
52
|
-
|
53
|
-
|
66
|
+
@Config("role_session_duration_seconds")
|
67
|
+
@ConfigDefault("null")
|
68
|
+
def getRoleSessionDurationSeconds: Optional[Int]
|
54
69
|
|
55
|
-
|
56
|
-
|
57
|
-
|
70
|
+
@Config("scope_down_policy")
|
71
|
+
@ConfigDefault("null")
|
72
|
+
def getScopeDownPolicy: Optional[String]
|
58
73
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
@Config("web_identity_token_file")
|
64
|
-
@ConfigDefault("null")
|
65
|
-
def getWebIdentityTokenFile: Optional[String]
|
66
|
-
}
|
74
|
+
@Config("web_identity_token_file")
|
75
|
+
@ConfigDefault("null")
|
76
|
+
def getWebIdentityTokenFile: Optional[String]
|
77
|
+
}
|
67
78
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
}
|
79
|
+
def apply(task: Task): AwsCredentials = {
|
80
|
+
new AwsCredentials(task)
|
81
|
+
}
|
72
82
|
}
|
73
83
|
|
74
|
-
class AwsCredentials(task: Task)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
case "properties" =>
|
101
|
-
new SystemPropertiesCredentialsProvider
|
102
|
-
|
103
|
-
case "anonymous" =>
|
104
|
-
new AWSStaticCredentialsProvider(new AnonymousAWSCredentials)
|
105
|
-
|
106
|
-
case "session" =>
|
107
|
-
new AWSStaticCredentialsProvider(new BasicSessionCredentials(
|
108
|
-
getRequiredOption(task.getAccessKeyId, "access_key_id"),
|
109
|
-
getRequiredOption(task.getSecretAccessKey, "secret_access_key"),
|
110
|
-
getRequiredOption(task.getSessionToken, "session_token")
|
111
|
-
))
|
112
|
-
|
113
|
-
case "assume_role" =>
|
114
|
-
// NOTE: Are http_proxy, endpoint, region required when assuming role?
|
115
|
-
val builder = new STSAssumeRoleSessionCredentialsProvider.Builder(
|
116
|
-
getRequiredOption(task.getRoleArn, "role_arn"),
|
117
|
-
getRequiredOption(task.getRoleSessionName, "role_session_name")
|
118
|
-
)
|
119
|
-
task.getRoleExternalId.ifPresent(v => builder.withExternalId(v))
|
120
|
-
task.getRoleSessionDurationSeconds.ifPresent(v => builder.withRoleSessionDurationSeconds(v))
|
121
|
-
task.getScopeDownPolicy.ifPresent(v => builder.withScopeDownPolicy(v))
|
122
|
-
|
123
|
-
builder.build()
|
124
|
-
|
125
|
-
case "web_identity_token" =>
|
126
|
-
WebIdentityTokenCredentialsProvider.builder()
|
127
|
-
.roleArn(getRequiredOption(task.getRoleArn, "role_arn"))
|
128
|
-
.roleSessionName(getRequiredOption(task.getRoleSessionName, "role_session_name"))
|
129
|
-
.webIdentityTokenFile(getRequiredOption(task.getWebIdentityTokenFile, "web_identity_token_file"))
|
130
|
-
.build()
|
131
|
-
|
132
|
-
case "default" =>
|
133
|
-
new DefaultAWSCredentialsProviderChain
|
134
|
-
|
135
|
-
case am =>
|
136
|
-
throw new ConfigException(s"'$am' is unsupported: `auth_method` must be one of ['basic', 'env', 'instance', 'profile', 'properties', 'anonymous', 'session', 'assume_role', 'default'].")
|
84
|
+
class AwsCredentials(task: Task) {
|
85
|
+
|
86
|
+
def createAwsCredentialsProvider: AWSCredentialsProvider = {
|
87
|
+
task.getAuthMethod match {
|
88
|
+
case "basic" =>
|
89
|
+
new AWSStaticCredentialsProvider(
|
90
|
+
new BasicAWSCredentials(
|
91
|
+
getRequiredOption(task.getAccessKeyId, "access_key_id"),
|
92
|
+
getRequiredOption(task.getSecretAccessKey, "secret_access_key")
|
93
|
+
)
|
94
|
+
)
|
95
|
+
|
96
|
+
case "env" =>
|
97
|
+
new EnvironmentVariableCredentialsProvider
|
98
|
+
|
99
|
+
case "instance" =>
|
100
|
+
// NOTE: combination of InstanceProfileCredentialsProvider and ContainerCredentialsProvider
|
101
|
+
new EC2ContainerCredentialsProviderWrapper
|
102
|
+
|
103
|
+
case "profile" =>
|
104
|
+
if (task.getProfileFile.isPresent) {
|
105
|
+
val pf: ProfilesConfigFile = new ProfilesConfigFile(
|
106
|
+
task.getProfileFile.get().getFile
|
107
|
+
)
|
108
|
+
new ProfileCredentialsProvider(pf, task.getProfileName)
|
137
109
|
}
|
110
|
+
else new ProfileCredentialsProvider(task.getProfileName)
|
111
|
+
|
112
|
+
case "properties" =>
|
113
|
+
new SystemPropertiesCredentialsProvider
|
114
|
+
|
115
|
+
case "anonymous" =>
|
116
|
+
new AWSStaticCredentialsProvider(new AnonymousAWSCredentials)
|
117
|
+
|
118
|
+
case "session" =>
|
119
|
+
new AWSStaticCredentialsProvider(
|
120
|
+
new BasicSessionCredentials(
|
121
|
+
getRequiredOption(task.getAccessKeyId, "access_key_id"),
|
122
|
+
getRequiredOption(task.getSecretAccessKey, "secret_access_key"),
|
123
|
+
getRequiredOption(task.getSessionToken, "session_token")
|
124
|
+
)
|
125
|
+
)
|
126
|
+
|
127
|
+
case "assume_role" =>
|
128
|
+
// NOTE: Are http_proxy, endpoint, region required when assuming role?
|
129
|
+
val builder = new STSAssumeRoleSessionCredentialsProvider.Builder(
|
130
|
+
getRequiredOption(task.getRoleArn, "role_arn"),
|
131
|
+
getRequiredOption(task.getRoleSessionName, "role_session_name")
|
132
|
+
)
|
133
|
+
task.getRoleExternalId.ifPresent(v => builder.withExternalId(v))
|
134
|
+
task.getRoleSessionDurationSeconds.ifPresent(v =>
|
135
|
+
builder.withRoleSessionDurationSeconds(v)
|
136
|
+
)
|
137
|
+
task.getScopeDownPolicy.ifPresent(v => builder.withScopeDownPolicy(v))
|
138
|
+
|
139
|
+
builder.build()
|
140
|
+
|
141
|
+
case "web_identity_token" =>
|
142
|
+
WebIdentityTokenCredentialsProvider
|
143
|
+
.builder()
|
144
|
+
.roleArn(getRequiredOption(task.getRoleArn, "role_arn"))
|
145
|
+
.roleSessionName(
|
146
|
+
getRequiredOption(task.getRoleSessionName, "role_session_name")
|
147
|
+
)
|
148
|
+
.webIdentityTokenFile(
|
149
|
+
getRequiredOption(
|
150
|
+
task.getWebIdentityTokenFile,
|
151
|
+
"web_identity_token_file"
|
152
|
+
)
|
153
|
+
)
|
154
|
+
.build()
|
155
|
+
|
156
|
+
case "default" =>
|
157
|
+
new DefaultAWSCredentialsProviderChain
|
158
|
+
|
159
|
+
case am =>
|
160
|
+
throw new ConfigException(
|
161
|
+
s"'$am' is unsupported: `auth_method` must be one of ['basic', 'env', 'instance', 'profile', 'properties', 'anonymous', 'session', 'assume_role', 'default']."
|
162
|
+
)
|
138
163
|
}
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
164
|
+
}
|
165
|
+
|
166
|
+
private def getRequiredOption[A](o: Optional[A], name: String): A = {
|
167
|
+
o.orElseThrow(() =>
|
168
|
+
new ConfigException(
|
169
|
+
s"`$name` must be set when `auth_method` is ${task.getAuthMethod}."
|
170
|
+
)
|
171
|
+
)
|
172
|
+
}
|
146
173
|
|
147
174
|
}
|