1
1
package com .avast .clients .storage .gcs
2
2
3
3
import better .files .File
4
- import cats .data .EitherT
5
4
import cats .effect .implicits .catsEffectSyntaxBracket
6
5
import cats .effect .{Blocker , ContextShift , Resource , Sync }
7
6
import cats .syntax .all ._
@@ -10,7 +9,7 @@ import com.avast.clients.storage.{ConfigurationException, GetResult, HeadResult,
10
9
import com .avast .scala .hashes .Sha256
11
10
import com .google .auth .oauth2 .ServiceAccountCredentials
12
11
import com .google .cloud .ServiceOptions
13
- import com .google .cloud .storage .{Blob , Bucket , Storage , StorageOptions , StorageException => GcStorageException }
12
+ import com .google .cloud .storage .{Blob , BlobId , Storage , StorageOptions , StorageException => GcStorageException }
14
13
import com .typesafe .config .{Config , ConfigFactory }
15
14
import com .typesafe .scalalogging .StrictLogging
16
15
import pureconfig .error .ConfigReaderException
@@ -23,7 +22,9 @@ import java.nio.charset.StandardCharsets
23
22
import java .nio .file .StandardOpenOption
24
23
import java .security .{DigestOutputStream , MessageDigest }
25
24
26
- class GcsStorageBackend [F [_]: Sync : ContextShift ](bucket : Bucket )(blocker : Blocker ) extends StorageBackend [F ] with StrictLogging {
25
+ class GcsStorageBackend [F [_]: Sync : ContextShift ](storageClient : Storage , bucketName : String )(blocker : Blocker )
26
+ extends StorageBackend [F ]
27
+ with StrictLogging {
27
28
private val FileStreamOpenOptions = Seq (StandardOpenOption .WRITE , StandardOpenOption .CREATE , StandardOpenOption .TRUNCATE_EXISTING )
28
29
29
30
override def head (sha256 : Sha256 ): F [Either [StorageException , HeadResult ]] = {
@@ -74,7 +75,7 @@ class GcsStorageBackend[F[_]: Sync: ContextShift](bucket: Bucket)(blocker: Block
74
75
for {
75
76
objectPath <- Sync [F ].delay(composeBlobPath(sha256))
76
77
result <- blocker.delay {
77
- Option (bucket .get(objectPath))
78
+ Option (storageClient .get(BlobId .of(bucketName, objectPath) ))
78
79
}
79
80
} yield result
80
81
}
@@ -117,34 +118,28 @@ object GcsStorageBackend {
117
118
private val DefaultConfig = ConfigFactory .defaultReference().getConfig(" gcsBackendDefaults" )
118
119
119
120
def fromConfig [F [_]: Sync : ContextShift ](config : Config ,
120
- blocker : Blocker ): EitherT [F , ConfigurationException , Resource [F , GcsStorageBackend [F ]]] = {
121
-
122
- def composeConfig : EitherT [F , ConfigurationException , GcsBackendConfiguration ] = EitherT {
123
- Sync [F ].delay {
124
- pureconfig.ConfigSource
125
- .fromConfig(config.withFallback(DefaultConfig ))
126
- .load[GcsBackendConfiguration ]
127
- .leftMap { failures =>
128
- ConfigurationException (" Could not load config" , new ConfigReaderException [GcsBackendConfiguration ](failures))
129
- }
130
- }
121
+ blocker : Blocker ): Either [ConfigurationException , Resource [F , GcsStorageBackend [F ]]] = {
122
+
123
+ def composeConfig : Either [ConfigurationException , GcsBackendConfiguration ] = {
124
+ pureconfig.ConfigSource
125
+ .fromConfig(config.withFallback(DefaultConfig ))
126
+ .load[GcsBackendConfiguration ]
127
+ .leftMap { failures =>
128
+ ConfigurationException (" Could not load config" , new ConfigReaderException [GcsBackendConfiguration ](failures))
129
+ }
131
130
}
132
131
133
- {
134
- for {
135
- conf <- composeConfig
136
- storageClient <- prepareStorageClient(conf, blocker)
137
- bucket <- getBucket(conf, storageClient, blocker)
138
- } yield (storageClient, bucket)
139
- }.map {
140
- case (storage, bucket) =>
141
- Resource
142
- .fromAutoCloseable {
143
- Sync [F ].pure(storage)
144
- }
145
- .map { _ =>
146
- new GcsStorageBackend [F ](bucket)(blocker)
147
- }
132
+ for {
133
+ conf <- composeConfig
134
+ storageClient <- prepareStorageClient(conf, blocker)
135
+ } yield {
136
+ Resource
137
+ .fromAutoCloseable {
138
+ Sync [F ].pure(storageClient)
139
+ }
140
+ .map { storageClient =>
141
+ new GcsStorageBackend [F ](storageClient, conf.bucketName)(blocker)
142
+ }
148
143
}
149
144
}
150
145
@@ -154,66 +149,36 @@ object GcsStorageBackend {
154
149
}
155
150
156
151
def prepareStorageClient [F [_]: Sync : ContextShift ](conf : GcsBackendConfiguration ,
157
- blocker : Blocker ): EitherT [F , ConfigurationException , Storage ] = {
158
- EitherT {
159
- blocker.delay {
160
- Either
161
- .catchNonFatal {
162
- val credentialsFileContent = conf.credentialsFile
163
- .map { credentialsFilePath =>
164
- new FileInputStream (credentialsFilePath)
165
- }
166
- .orElse {
167
- sys.env.get(" GOOGLE_APPLICATION_CREDENTIALS_RAW" ).map { credentialFileRaw =>
168
- new ByteArrayInputStream (credentialFileRaw.getBytes(StandardCharsets .UTF_8 ))
169
- }
170
- }
171
-
172
- val builder = credentialsFileContent match {
173
- case Some (inputStream) =>
174
- StorageOptions .newBuilder
175
- .setCredentials(ServiceAccountCredentials .fromStream(inputStream))
176
- case None =>
177
- StorageOptions .getDefaultInstance.toBuilder
178
- }
179
-
180
- builder
181
- .setProjectId(conf.projectId)
182
- .setRetrySettings(ServiceOptions .getNoRetrySettings)
183
-
184
- builder.build.getService
152
+ blocker : Blocker ): Either [ConfigurationException , Storage ] = {
153
+ Either
154
+ .catchNonFatal {
155
+ val credentialsFileContent = conf.credentialsFile
156
+ .map { credentialsFilePath =>
157
+ new FileInputStream (credentialsFilePath)
185
158
}
186
- .leftMap { e =>
187
- ConfigurationException (" Could not create GCS client" , e)
188
- }
189
- }
190
- }
191
- }
192
-
193
- def getBucket [F [_]: Sync : ContextShift ](conf : GcsBackendConfiguration ,
194
- storageClient : Storage ,
195
- blocker : Blocker ): EitherT [F , ConfigurationException , Bucket ] = {
196
- EitherT {
197
- blocker
198
- .delay {
199
- Either
200
- .catchNonFatal {
201
- Option (storageClient.get(conf.bucketName, Storage .BucketGetOption .userProject(conf.projectId)))
159
+ .orElse {
160
+ sys.env.get(" GOOGLE_APPLICATION_CREDENTIALS_RAW" ).map { credentialFileRaw =>
161
+ new ByteArrayInputStream (credentialFileRaw.getBytes(StandardCharsets .UTF_8 ))
202
162
}
203
- }
204
- .map {
205
- _.leftMap { e =>
206
- ConfigurationException (s " Attempt to get bucket ${conf.bucketName} failed " , e)
207
- }.flatMap {
208
- case Some (bucket) =>
209
- Right (bucket)
210
- case None =>
211
- Left {
212
- ConfigurationException (s " Bucket ${conf.bucketName} does not exist " )
213
- }
214
163
}
164
+
165
+ val builder = credentialsFileContent match {
166
+ case Some (inputStream) =>
167
+ StorageOptions .newBuilder
168
+ .setCredentials(ServiceAccountCredentials .fromStream(inputStream))
169
+ case None =>
170
+ StorageOptions .getDefaultInstance.toBuilder
215
171
}
216
- }
172
+
173
+ builder
174
+ .setProjectId(conf.projectId)
175
+ .setRetrySettings(ServiceOptions .getNoRetrySettings)
176
+
177
+ builder.build.getService
178
+ }
179
+ .leftMap { e =>
180
+ ConfigurationException (" Could not create GCS client" , e)
181
+ }
217
182
}
218
183
}
219
184
0 commit comments