diff --git a/src/main/scala/net/kemitix/s3thorp/Sync.scala b/src/main/scala/net/kemitix/s3thorp/Sync.scala index cb61cbb..74fdd19 100644 --- a/src/main/scala/net/kemitix/s3thorp/Sync.scala +++ b/src/main/scala/net/kemitix/s3thorp/Sync.scala @@ -17,6 +17,9 @@ class Sync(s3Client: S3Client) override def objectHead(bucket: Bucket, remoteKey: RemoteKey)= s3Client.objectHead(bucket, remoteKey) + override def upload(localFile: LocalFile, bucket: Bucket, remoteKey: RemoteKey): IO[Unit] = + s3Client.upload(localFile, bucket, remoteKey) + def run(c: Config): IO[Unit] = for { _ <- putStrLn(s"Bucket: ${c.bucket}, Prefix: ${c.prefix}, Source: ${c.source}") _ <- { diff --git a/src/main/scala/net/kemitix/s3thorp/awssdk/ReactiveS3Client.scala b/src/main/scala/net/kemitix/s3thorp/awssdk/ReactiveS3Client.scala index 7406da1..89cc32d 100644 --- a/src/main/scala/net/kemitix/s3thorp/awssdk/ReactiveS3Client.scala +++ b/src/main/scala/net/kemitix/s3thorp/awssdk/ReactiveS3Client.scala @@ -3,8 +3,9 @@ package net.kemitix.s3thorp.awssdk import cats.effect.IO import com.github.j5ik2o.reactive.aws.s3.S3AsyncClient import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient -import software.amazon.awssdk.services.s3.model.{HeadObjectRequest, NoSuchKeyException} import net.kemitix.s3thorp.Sync.{Bucket, LocalFile, RemoteKey} +import software.amazon.awssdk.core.async.AsyncRequestBody +import software.amazon.awssdk.services.s3.model.{HeadObjectRequest, NoSuchKeyException, PutObjectRequest} import software.amazon.awssdk.services.s3.{S3AsyncClient => JavaS3AsyncClient} private class ReactiveS3Client extends S3Client { @@ -24,4 +25,17 @@ private class ReactiveS3Client extends S3Client { case _: NoSuchKeyException => IO(None) } } + + override def upload(localFile: LocalFile, bucket: Bucket, remoteKey: RemoteKey): IO[Unit] = { + val request = PutObjectRequest.builder() + .bucket(bucket) + .key(remoteKey) + .build() + val body = AsyncRequestBody.fromFile(localFile) + try { + for { + _ <- s3Client.putObject(request, body) + } yield () + } + } } diff --git a/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala b/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala index 4cf8517..3e55c7c 100644 --- a/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala +++ b/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala @@ -7,6 +7,8 @@ trait S3Client { def objectHead(bucket: Bucket, remoteKey: RemoteKey): IO[Option[(MD5Hash, LastModified)]] + def upload(localFile: LocalFile, bucket: Bucket, remoteKey: RemoteKey): IO[Unit] + } object S3Client { diff --git a/src/test/scala/net/kemitix/s3thorp/DummyS3Client.scala b/src/test/scala/net/kemitix/s3thorp/DummyS3Client.scala new file mode 100644 index 0000000..78f86be --- /dev/null +++ b/src/test/scala/net/kemitix/s3thorp/DummyS3Client.scala @@ -0,0 +1,12 @@ +package net.kemitix.s3thorp + +import cats.effect.IO +import net.kemitix.s3thorp.Sync.{Bucket, LastModified, LocalFile, MD5Hash, RemoteKey} +import net.kemitix.s3thorp.awssdk.S3Client + +trait DummyS3Client extends S3Client { + + override def objectHead(bucket: Bucket, remoteKey: RemoteKey): IO[Option[(MD5Hash, LastModified)]] = ??? + + override def upload(localFile: LocalFile, bucket: Bucket, remoteKey: RemoteKey): IO[Unit] = ??? +} diff --git a/src/test/scala/net/kemitix/s3thorp/S3MetaDataEnricherSuite.scala b/src/test/scala/net/kemitix/s3thorp/S3MetaDataEnricherSuite.scala index 8bce7a1..0512465 100644 --- a/src/test/scala/net/kemitix/s3thorp/S3MetaDataEnricherSuite.scala +++ b/src/test/scala/net/kemitix/s3thorp/S3MetaDataEnricherSuite.scala @@ -14,7 +14,7 @@ class S3MetaDataEnricherSuite extends FunSpec { private val prefix = "prefix" private val config = Config("bucket", prefix, source) - new S3MetaDataEnricher { + new S3MetaDataEnricher with DummyS3Client { describe("key generator") { val subject = generateKey(config)_ @@ -36,7 +36,6 @@ class S3MetaDataEnricherSuite extends FunSpec { } } } - override def objectHead(bucket: String, key: String) = ??? } describe("enrich with metadata") { @@ -45,7 +44,7 @@ class S3MetaDataEnricherSuite extends FunSpec { describe("when remote exists") { val hash = "hash" val lastModified = Instant.now() - new S3MetaDataEnricher { + new S3MetaDataEnricher with DummyS3Client { override def objectHead(bucket: String, key: String) = IO(Some((hash, lastModified))) it("returns metadata") { val expectedMetadata = S3MetaData(localFile, s"$prefix/$local", hash, lastModified) @@ -56,7 +55,7 @@ class S3MetaDataEnricherSuite extends FunSpec { } } describe("when remote doesn't exist") { - new S3MetaDataEnricher { + new S3MetaDataEnricher with DummyS3Client { override def objectHead(bucket: String, key: String) = IO(None) it("returns file to upload") { val result = enrichWithS3MetaData(config)(localFile).compile.toList.unsafeRunSync().head diff --git a/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala b/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala index acacd36..8c6c60b 100644 --- a/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala +++ b/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala @@ -11,7 +11,7 @@ class SyncSuite extends FunSpec { describe("s3client thunk") { val hash = "hash" val lastModified = Instant.now() - val sync = new Sync(new S3Client { + val sync = new Sync(new S3Client with DummyS3Client { override def objectHead(bucket: String, key: String) = IO(Some((hash, lastModified))) }) describe("objectHead") {