1515 */
1616package com .google .cloud .teleport .spanner ;
1717
18+ import com .google .cloud .spanner .DatabaseNotFoundException ;
1819import com .google .cloud .spanner .Options .RpcPriority ;
1920import com .google .cloud .spanner .SpannerOptions ;
2021import com .google .cloud .teleport .metadata .Template ;
2627import com .google .cloud .teleport .spanner .iam .IAMCheckResult ;
2728import com .google .cloud .teleport .spanner .iam .IAMPermissionsChecker ;
2829import com .google .cloud .teleport .spanner .iam .IAMRequirementsCreator ;
29- import com .google .cloud .teleport .spanner .iam .IAMResourceRequirements ;
3030import com .google .cloud .teleport .spanner .spannerio .SpannerConfig ;
31- import java .util .Collections ;
31+ import java .io .IOException ;
32+ import java .security .GeneralSecurityException ;
3233import org .apache .beam .runners .dataflow .options .DataflowPipelineOptions ;
3334import org .apache .beam .sdk .Pipeline ;
3435import org .apache .beam .sdk .PipelineResult ;
35- import org .apache .beam .sdk .extensions .gcp .options .GcpOptions ;
3636import org .apache .beam .sdk .options .Default ;
3737import org .apache .beam .sdk .options .Description ;
3838import org .apache .beam .sdk .options .PipelineOptions ;
3939import org .apache .beam .sdk .options .PipelineOptionsFactory ;
4040import org .apache .beam .sdk .options .ValueProvider ;
4141import org .apache .beam .sdk .options .ValueProvider .NestedValueProvider ;
4242import org .apache .beam .sdk .transforms .SerializableFunction ;
43+ import org .slf4j .Logger ;
44+ import org .slf4j .LoggerFactory ;
4345
4446/**
4547 * Avro to Cloud Spanner Import pipeline.
6567 "The input Cloud Storage path must exist, and it must include a <a href=\" https://cloud.google.com/spanner/docs/import-non-spanner#create-export-json\" >spanner-export.json</a> file that contains a JSON description of files to import."
6668 })
6769public class ImportPipeline {
70+ private static final Logger LOG = LoggerFactory .getLogger (ImportPipeline .class );
6871
6972 /** Options for {@link ImportPipeline}. */
7073 public interface Options extends PipelineOptions {
@@ -258,7 +261,6 @@ public static void main(String[] args) {
258261 options .getDdlCreationTimeoutInMinutes (),
259262 options .getEarlyIndexCreateThreshold ()));
260263
261- validateRequiredPermissions (options );
262264 PipelineResult result = p .run ();
263265
264266 if (options .getWaitUntilFinish ()
@@ -271,24 +273,45 @@ public static void main(String[] args) {
271273 }
272274 }
273275
274- private static void validateRequiredPermissions (Options options ) {
275- IAMResourceRequirements spannerRequirements =
276- IAMRequirementsCreator .createSpannerResourceRequirement ();
277- GcpOptions gcpOptions = options .as (GcpOptions .class );
278-
279- IAMPermissionsChecker iamPermissionsChecker =
280- new IAMPermissionsChecker (gcpOptions .getProject (), gcpOptions );
281- IAMCheckResult missingPermission =
282- iamPermissionsChecker .check (Collections .singletonList (spannerRequirements ));
283- if (missingPermission .isSuccess ()) {
276+ private static void validateRequiredPermissions (SpannerConfig spannerConfig ) {
277+ if (!spannerConfig .getInstanceId ().isAccessible ()) {
278+ // If instance id is not accessible, then the current context is not runtime. Hence,
279+ // validation is not applicable.
284280 return ;
285281 }
286- String errorString =
287- "For resource: "
288- + missingPermission .getResourceName ()
289- + ", missing permissions: "
290- + missingPermission .getMissingPermissions ()
291- + ";" ;
292- throw new RuntimeException (errorString );
282+ String instanceId = spannerConfig .getInstanceId ().get ();
283+ String databaseId = spannerConfig .getDatabaseId ().get ();
284+ IAMCheckResult iamCheckResult ;
285+ try {
286+ IAMPermissionsChecker iamPermissionsChecker =
287+ new IAMPermissionsChecker (spannerConfig .getProjectId ().get ());
288+ try {
289+
290+ iamCheckResult =
291+ iamPermissionsChecker .checkSpannerDatabaseRequirements (
292+ IAMRequirementsCreator .createSpannerWriteResourceRequirement (),
293+ instanceId ,
294+ databaseId );
295+ } catch (DatabaseNotFoundException e ) {
296+ // If DatabaseNotFoundException exception is thrown, then validation at instance level need
297+ // to be performed.
298+ iamCheckResult =
299+ iamPermissionsChecker .checkSpannerInstanceRequirements (
300+ IAMRequirementsCreator .createSpannerWriteResourceRequirement (), instanceId );
301+ }
302+ if (iamCheckResult .isPermissionsAvailable ()) {
303+ return ;
304+ }
305+ String errorString =
306+ "For resource: "
307+ + iamCheckResult .getResourceName ()
308+ + ", missing permissions: "
309+ + iamCheckResult .getMissingPermissions ()
310+ + ";" ;
311+ throw new RuntimeException (errorString );
312+ } catch (GeneralSecurityException | IOException e ) {
313+ LOG .error ("Error while validating permissions for spanner" , e );
314+ throw new RuntimeException (e );
315+ }
293316 }
294317}
0 commit comments