From b14d55f096709af993fb4967a96805d44b891b99 Mon Sep 17 00:00:00 2001 From: Karim Wadie Date: Tue, 18 Apr 2023 15:07:06 +0200 Subject: [PATCH] fix for messed up commit history: added gcs as backup policy store --- README.md | 8 +- scripts/prepare_backup_storage_projects.sh | 4 +- .../configurator/ConfiguratorController.java | 20 +- .../configurator/Environment.java | 12 +- .../dispatcher/DispatcherController.java | 4 +- .../dispatcher/Environment.java | 7 +- services/library/pom.xml | 5 + .../bq_snapshot_manager/entities/Globals.java | 6 - .../entities/TableSpec.java | 8 + .../entities/backup_policy/BackupPolicy.java | 318 +++++++++++++----- ...TagFields.java => BackupPolicyFields.java} | 3 +- .../functions/f01_dispatcher/Dispatcher.java | 6 +- .../f01_dispatcher/DispatcherConfig.java | 10 +- .../f02_configurator/Configurator.java | 30 +- .../f02_configurator/ConfiguratorConfig.java | 12 +- .../f03_snapshoter/BigQuerySnapshoter.java | 5 +- .../f03_snapshoter/GCSSnapshoter.java | 8 +- .../f03_snapshoter/SnapshoterConfig.java | 10 +- .../functions/f04_tagger/Tagger.java | 29 +- .../functions/f04_tagger/TaggerConfig.java | 16 +- .../helpers/LoggingHelper.java | 9 +- .../helpers/TrackingHelper.java | 9 +- .../bq_snapshot_manager/helpers/Utils.java | 4 +- .../backup_policy/BackupPolicyService.java | 16 + .../BackupPolicyServiceDataCatalogImpl.java} | 59 ++-- .../BackupPolicyServiceFireStoreImpl.java | 59 ++++ .../BackupPolicyServiceGCSImpl.java | 59 ++++ .../services/bq/BigQueryServiceImpl.java | 2 - .../services/catalog/DataCatalogService.java | 17 - .../entities/BackupPolicyTest.java | 48 +-- .../BigQueryScopeListerTest.java | 2 +- .../f01_dispatcher/DispatcherTest.java | 3 +- .../f02_configurator/ConfiguratorTest.java | 22 +- .../BigQuerySnapshoterTest.java | 2 +- .../f03_snapshoter/GCSSnapshoterTest.java | 2 +- .../ControllerExceptionHelperTest.java | 14 +- .../helpers/TrackingHelperTest.java | 2 +- .../helpers/UtilsTest.java | 2 +- ...ckupPolicyServiceDataCatalogImplTest.java} | 16 +- .../BigQuerySnapshoterController.java | 3 +- .../snapshoter_bq/Environment.java | 6 +- .../snapshoter_gcs/Environment.java | 7 +- .../GCSSnapshoterController.java | 3 +- .../tagger/Environment.java | 9 +- .../tagger/TaggerController.java | 25 +- terraform/main.tf | 13 +- terraform/modules/bigquery/main.tf | 24 +- .../bigquery/schema/ext_backup_policies.json | 88 +++++ terraform/modules/bigquery/variables.tf | 4 + .../bigquery/views/v_audit_log_by_table.tpl | 2 +- .../bigquery/views/v_service_calls.tpl | 2 +- terraform/modules/gcs/main.tf | 24 +- terraform/modules/gcs/output.tf | 4 + terraform/modules/gcs/variables.tf | 10 +- terraform/modules/iam/main.tf | 16 + terraform/variables.tf | 7 +- 56 files changed, 826 insertions(+), 289 deletions(-) delete mode 100644 services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/Globals.java rename services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/{DataCatalogBackupPolicyTagFields.java => BackupPolicyFields.java} (82%) create mode 100644 services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyService.java rename services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/{catalog/DataCatalogServiceImpl.java => backup_policy/BackupPolicyServiceDataCatalogImpl.java} (67%) create mode 100644 services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceFireStoreImpl.java create mode 100644 services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceGCSImpl.java delete mode 100644 services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/catalog/DataCatalogService.java rename services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/services/{DataCatalogServiceImplTest.java => BackupPolicyServiceDataCatalogImplTest.java} (75%) create mode 100644 terraform/modules/bigquery/schema/ext_backup_policies.json diff --git a/README.md b/README.md index 27b1f15..aeef92f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ * [BigQuery Snapshoter](#bigquery-snapshoter) * [GCS Snapshoter](#gcs-snapshoter) * [Tagger](#tagger) - * [Design Notes](#design-notes) + * [Design Notes](#design-notes) * [Assumptions](#assumptions) * [Deployment](#deployment) * [Install Maven](#install-maven) @@ -135,16 +135,16 @@ A cloud scheduler is used to send a BigQuery “Scan Scope” to the dispatcher The solution uses multiple steps, as explained above, to list, backup and tag tables. These steps are designed so that each one of them is responsible for doing one main task and allow for checkpointing to handle retries in a cost-efficient way, and using PubSub to decouple these steps from each other. For example, if a table is backed up in a single run, via the Snpashoter step, -and then the Tagger step fails to update its backup policy (i.e. last_update_at field) +and then the Tagger step fails to update its backup policy (i.e. last_update_at field) due to temporarily GCP API quotas/limits with the underlying service, the request will not be acknowledged to PubSub, and it will be retried again with exponential backoff. In this case only the tagging logic will be retried and not the entire backup operation -that was already successful. +that was already successful. These steps are implemented in separate Cloud Run services, vs one service with multiple endpoints, to allow fine grain control on the concurrency, CPU, Memory and timeout settings for each step. This is especially useful since each step could use different settings depending on its traffic pattern and processing requirements. For example: * The Dispatcher executes once per run while the other services executes once per table; meaning they could use different concurrency settings (i.e. number of container, requests per container). -Another + Another * The Dispatcher uses relatively higher memory since it's listing all tables in the scan scope which could be in thousands * The Dispatcher and GCS Snapshoter needs relatively longer time to finish compared to the BQ Snapshoter. They could use different timeout settings to avoid un-wanted retries by PubSub diff --git a/scripts/prepare_backup_storage_projects.sh b/scripts/prepare_backup_storage_projects.sh index 5ad167d..bdf10ce 100755 --- a/scripts/prepare_backup_storage_projects.sh +++ b/scripts/prepare_backup_storage_projects.sh @@ -35,9 +35,9 @@ do echo "Preparing GCS Snapshoter SA permissions on backup storage project ${project} .." # GCS Snapshoter needs to write to GCS - # permission: storage.objects.create + # permission: storage.objects.create, storage.objects.delete gcloud projects add-iam-policy-binding "${project}" \ --member="serviceAccount:${SA_SNAPSHOTER_GCS_EMAIL}" \ - --role="roles/storage.objectCreator" + --role="roles/storage.objectAdmin" done diff --git a/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/ConfiguratorController.java b/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/ConfiguratorController.java index 1cac659..e63ea60 100644 --- a/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/ConfiguratorController.java +++ b/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/ConfiguratorController.java @@ -19,18 +19,17 @@ import com.google.cloud.Tuple; import com.google.cloud.pso.bq_snapshot_manager.entities.NonRetryableApplicationException; import com.google.cloud.pso.bq_snapshot_manager.entities.PubSubEvent; -import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.FallbackBackupPolicy; import com.google.cloud.pso.bq_snapshot_manager.functions.f02_configurator.Configurator; import com.google.cloud.pso.bq_snapshot_manager.functions.f02_configurator.ConfiguratorRequest; import com.google.cloud.pso.bq_snapshot_manager.functions.f02_configurator.ConfiguratorResponse; -import com.google.cloud.pso.bq_snapshot_manager.functions.f04_tagger.TaggerRequest; -import com.google.cloud.pso.bq_snapshot_manager.functions.f04_tagger.TaggerResponse; import com.google.cloud.pso.bq_snapshot_manager.helpers.ControllerExceptionHelper; import com.google.cloud.pso.bq_snapshot_manager.helpers.LoggingHelper; import com.google.cloud.pso.bq_snapshot_manager.helpers.TrackingHelper; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyServiceGCSImpl; import com.google.cloud.pso.bq_snapshot_manager.services.bq.BigQueryServiceImpl; -import com.google.cloud.pso.bq_snapshot_manager.services.catalog.DataCatalogServiceImpl; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyService; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyServiceFireStoreImpl; import com.google.cloud.pso.bq_snapshot_manager.services.pubsub.PubSubServiceImpl; import com.google.cloud.pso.bq_snapshot_manager.services.set.GCSPersistentSetImpl; import com.google.gson.Gson; @@ -63,7 +62,8 @@ public ConfiguratorController() throws JsonProcessingException { logger = new LoggingHelper( ConfiguratorController.class.getSimpleName(), functionNumber, - environment.getProjectId() + environment.getProjectId(), + environment.getApplicationName() ); logger.logInfoWithTracker( @@ -88,7 +88,7 @@ public ConfiguratorController() throws JsonProcessingException { public ResponseEntity receiveMessage(@RequestBody PubSubEvent requestBody) { - DataCatalogServiceImpl dataCatalogService = null; + BackupPolicyService backupPolicyService = null; // These values will be updated based on the execution flow and logged at the end ResponseEntity responseEntity; @@ -119,12 +119,12 @@ public ResponseEntity receiveMessage(@RequestBody PubSubEvent requestBody) { logger.logInfoWithTracker(configuratorRequest.isDryRun(), trackingId, configuratorRequest.getTargetTable(), String.format("Parsed Request: %s", configuratorRequest.toString())); - dataCatalogService = new DataCatalogServiceImpl(); + backupPolicyService = new BackupPolicyServiceGCSImpl(environment.getGcsBackupPoliciesBucket()); Configurator configurator = new Configurator( environment.toConfig(), new BigQueryServiceImpl(configuratorRequest.getTargetTable().getProject()), - dataCatalogService, + backupPolicyService, new PubSubServiceImpl(), new GCSPersistentSetImpl(environment.getGcsFlagsBucket()), fallbackBackupPolicy, @@ -152,8 +152,8 @@ public ResponseEntity receiveMessage(@RequestBody PubSubEvent requestBody) { } finally { - if (dataCatalogService != null) { - dataCatalogService.shutdown(); + if (backupPolicyService != null) { + backupPolicyService.shutdown(); } } diff --git a/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/Environment.java b/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/Environment.java index e419764..c488560 100644 --- a/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/Environment.java +++ b/services/configurator-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/configurator/Environment.java @@ -29,7 +29,8 @@ public ConfiguratorConfig toConfig (){ getProjectId(), getBqSnapshoterOutputTopic(), getGCSSnapshoterOutputTopic(), - getBackupTagTemplateId() + getBackupTagTemplateId(), + getApplicationName() ); } @@ -58,4 +59,13 @@ public String getBackupPolicyJson(){ public String getGcsFlagsBucket(){ return Utils.getConfigFromEnv("GCS_FLAGS_BUCKET", true); } + + public String getApplicationName(){ + return Utils.getConfigFromEnv("APPLICATION_NAME", true); + } + + public String getGcsBackupPoliciesBucket(){ + return Utils.getConfigFromEnv("GCS_BACKUP_POLICIES_BUCKET", true); + } + } diff --git a/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/DispatcherController.java b/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/DispatcherController.java index 98306f5..2466bc8 100644 --- a/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/DispatcherController.java +++ b/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/DispatcherController.java @@ -56,7 +56,9 @@ public DispatcherController() { logger = new LoggingHelper( DispatcherController.class.getSimpleName(), functionNumber, - environment.getProjectId()); + environment.getProjectId(), + environment.getApplicationName() + ); } @RequestMapping(value = "/", method = RequestMethod.POST) diff --git a/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/Environment.java b/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/Environment.java index f524c14..075f6a6 100644 --- a/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/Environment.java +++ b/services/dispatcher-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/dispatcher/Environment.java @@ -26,7 +26,8 @@ public DispatcherConfig toConfig(){ getProjectId(), getComputeRegionId(), getDataRegionId(), - getOutputTopic() + getOutputTopic(), + getApplicationName() ); } @@ -47,4 +48,8 @@ public String getDataRegionId(){ public String getGcsFlagsBucket(){ return Utils.getConfigFromEnv("GCS_FLAGS_BUCKET", true); } + + public String getApplicationName(){ + return Utils.getConfigFromEnv("APPLICATION_NAME", true); + } } diff --git a/services/library/pom.xml b/services/library/pom.xml index fa23963..fa22c14 100644 --- a/services/library/pom.xml +++ b/services/library/pom.xml @@ -117,6 +117,11 @@ google-cloud-datacatalog + + com.google.cloud + google-cloud-datastore + + com.google.apis google-api-services-cloudresourcemanager diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/Globals.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/Globals.java deleted file mode 100644 index 4c50492..0000000 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/Globals.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.google.cloud.pso.bq_snapshot_manager.entities; - -public class Globals { - public final static String APPLICATION_NAME = "bq_backup_manager"; - -} diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/TableSpec.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/TableSpec.java index 156803c..1e71426 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/TableSpec.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/TableSpec.java @@ -109,4 +109,12 @@ public String toResourceUrl(){ getTable() ); } + + public String toHivePartitionPostfix(){ + return String.format("project=%s/dataset=%s/table=%s", + project, + dataset, + table + ); + } } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/BackupPolicy.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/BackupPolicy.java index a778fb3..dbc812c 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/BackupPolicy.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/BackupPolicy.java @@ -3,42 +3,64 @@ import com.google.cloud.Timestamp; import com.google.cloud.datacatalog.v1.Tag; import com.google.cloud.datacatalog.v1.TagField; +import com.google.cloud.datastore.Entity; +import com.google.cloud.datastore.FullEntity; +import com.google.cloud.datastore.IncompleteKey; +import com.google.cloud.datastore.Key; +import com.google.cloud.pso.bq_snapshot_manager.functions.f02_configurator.ConfiguratorRequest; import com.google.cloud.pso.bq_snapshot_manager.helpers.Utils; import com.google.common.base.Objects; import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; public class BackupPolicy { + @SerializedName("backup_cron") private final String cron; + @SerializedName("backup_method") private final BackupMethod method; + @SerializedName("backup_time_travel_offset_days") private final TimeTravelOffsetDays timeTravelOffsetDays; - + @SerializedName("bq_snapshot_expiration_days") private final Double bigQuerySnapshotExpirationDays; + @SerializedName("backup_storage_project") private final String backupStorageProject; + @SerializedName("backup_operation_project") private final String backupOperationProject; + @SerializedName("bq_snapshot_storage_dataset") private final String bigQuerySnapshotStorageDataset; + @SerializedName("gcs_snapshot_storage_location") private final String gcsSnapshotStorageLocation; + @SerializedName("gcs_snapshot_format") private final GCSSnapshotFormat gcsExportFormat; + @SerializedName("gcs_csv_delimiter") private final String gcsCsvDelimiter; + @SerializedName("gcs_csv_export_header") private final Boolean gcsCsvExportHeader; + @SerializedName("gcs_avro_use_logical_types") private final Boolean gcsUseAvroLogicalTypes; + @SerializedName("config_source") private final BackupConfigSource configSource; + @SerializedName("last_backup_at") private Timestamp lastBackupAt; + @SerializedName("last_gcs_snapshot_storage_uri") private String lastBqSnapshotStorageUri; + @SerializedName("last_bq_snapshot_storage_uri") private String lastGcsSnapshotStorageUri; public BackupPolicy(BackupPolicyBuilder builder) throws IllegalArgumentException { - List missingFields = validate(builder); + List missingFields = validate(builder); if (!missingFields.isEmpty()) { throw new IllegalArgumentException( @@ -67,65 +89,65 @@ public BackupPolicy(BackupPolicyBuilder builder) throws IllegalArgumentException this.lastGcsSnapshotStorageUri = builder.lastGcsSnapshotStorageUri; } - public static List validate(BackupPolicyBuilder builder){ + public static List validate(BackupPolicyBuilder builder) { // validate that all required fields are provided depending on the backup method - List missingRequired = new ArrayList<>(); - List missingOptional = new ArrayList<>(); + List missingRequired = new ArrayList<>(); + List missingOptional = new ArrayList<>(); if (builder.cron == null) { - missingRequired.add(DataCatalogBackupPolicyTagFields.backup_cron); + missingRequired.add(BackupPolicyFields.backup_cron); } if (builder.method == null) { - missingRequired.add(DataCatalogBackupPolicyTagFields.backup_method); + missingRequired.add(BackupPolicyFields.backup_method); } if (builder.timeTravelOffsetDays == null) { - missingRequired.add(DataCatalogBackupPolicyTagFields.backup_time_travel_offset_days); + missingRequired.add(BackupPolicyFields.backup_time_travel_offset_days); } if (builder.configSource == null) { - missingRequired.add(DataCatalogBackupPolicyTagFields.config_source); + missingRequired.add(BackupPolicyFields.config_source); } if (builder.backupStorageProject == null) { - missingRequired.add(DataCatalogBackupPolicyTagFields.backup_storage_project); + missingRequired.add(BackupPolicyFields.backup_storage_project); } // if required params are missing return and don't continue with other checks - if(!missingRequired.isEmpty()){ + if (!missingRequired.isEmpty()) { return missingRequired; } if (builder.method.equals(BackupMethod.BIGQUERY_SNAPSHOT) || builder.method.equals(BackupMethod.BOTH)) { if (builder.bigQuerySnapshotStorageDataset == null) { - missingOptional.add(DataCatalogBackupPolicyTagFields.bq_snapshot_storage_dataset); + missingOptional.add(BackupPolicyFields.bq_snapshot_storage_dataset); } if (builder.bigQuerySnapshotExpirationDays == null) { - missingOptional.add(DataCatalogBackupPolicyTagFields.bq_snapshot_expiration_days); + missingOptional.add(BackupPolicyFields.bq_snapshot_expiration_days); } } // check for GCS params - if (builder.method.equals(BackupMethod.GCS_SNAPSHOT) ||builder. method.equals(BackupMethod.BOTH)) { + if (builder.method.equals(BackupMethod.GCS_SNAPSHOT) || builder.method.equals(BackupMethod.BOTH)) { String format = builder.gcsExportFormat == null ? null : GCSSnapshotFormat.getFormatAndCompression(builder.gcsExportFormat).x(); if (builder.gcsExportFormat == null) { - missingOptional.add(DataCatalogBackupPolicyTagFields.gcs_snapshot_format); + missingOptional.add(BackupPolicyFields.gcs_snapshot_format); } if (builder.gcsSnapshotStorageLocation == null) { - missingOptional.add(DataCatalogBackupPolicyTagFields.gcs_snapshot_storage_location); + missingOptional.add(BackupPolicyFields.gcs_snapshot_storage_location); } // check required fields for CSV exports - if(format != null && format.equals("CSV")){ - if(builder.gcsCsvDelimiter == null){ - missingOptional.add(DataCatalogBackupPolicyTagFields.gcs_csv_delimiter); + if (format != null && format.equals("CSV")) { + if (builder.gcsCsvDelimiter == null) { + missingOptional.add(BackupPolicyFields.gcs_csv_delimiter); } - if(builder.gcsCsvExportHeader == null){ - missingOptional.add(DataCatalogBackupPolicyTagFields.gcs_csv_export_header); + if (builder.gcsCsvExportHeader == null) { + missingOptional.add(BackupPolicyFields.gcs_csv_export_header); } } // check for required fields for avro export - if(format != null && format.equals("AVRO")){ - if(builder.gcsUseAvroLogicalTypes == null){ - missingOptional.add(DataCatalogBackupPolicyTagFields.gcs_avro_use_logical_types); + if (format != null && format.equals("AVRO")) { + if (builder.gcsUseAvroLogicalTypes == null) { + missingOptional.add(BackupPolicyFields.gcs_avro_use_logical_types); } } } @@ -206,6 +228,9 @@ public static BackupPolicy fromJson(String jsonStr) { return fromMap(jsonMap); } + public String toJson(){ + return new Gson().toJson(toMap()); + } @Override public String toString() { return "BackupPolicy{" + @@ -255,20 +280,20 @@ public Tag toDataCatalogTag(String tagTemplateId, String tagName) { .setTemplate(tagTemplateId); // required: cron - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.backup_cron.toString(), + tagBuilder.putFields(BackupPolicyFields.backup_cron.toString(), TagField.newBuilder().setStringValue(cron).build() - ); + ); // required: backup method - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.backup_method.toString(), + tagBuilder.putFields(BackupPolicyFields.backup_method.toString(), TagField.newBuilder().setEnumValue( - TagField.EnumValue.newBuilder().setDisplayName( - method.getText()) - .build()) - .build()); + TagField.EnumValue.newBuilder().setDisplayName( + method.getText()) + .build()) + .build()); // required: time travel - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.backup_time_travel_offset_days.toString(), + tagBuilder.putFields(BackupPolicyFields.backup_time_travel_offset_days.toString(), TagField.newBuilder().setEnumValue( TagField.EnumValue.newBuilder().setDisplayName( timeTravelOffsetDays.getText()) @@ -277,36 +302,36 @@ public Tag toDataCatalogTag(String tagTemplateId, String tagName) { //required: backup storage project TagField backupStorageProjectField = TagField.newBuilder().setStringValue(backupStorageProject).build(); - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.backup_storage_project.toString(), backupStorageProjectField); + tagBuilder.putFields(BackupPolicyFields.backup_storage_project.toString(), backupStorageProjectField); //optional: backup operation project - if(backupOperationProject != null){ - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.backup_operation_project.toString(), + if (backupOperationProject != null) { + tagBuilder.putFields(BackupPolicyFields.backup_operation_project.toString(), TagField.newBuilder().setStringValue(backupOperationProject).build()); } // optional: bq snapshot expiration if (bigQuerySnapshotExpirationDays != null) { - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.bq_snapshot_expiration_days.toString(), + tagBuilder.putFields(BackupPolicyFields.bq_snapshot_expiration_days.toString(), TagField.newBuilder().setDoubleValue(bigQuerySnapshotExpirationDays).build() - ); + ); } // optional: bq snapshot dataset if (bigQuerySnapshotStorageDataset != null) { - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.bq_snapshot_storage_dataset.toString(), + tagBuilder.putFields(BackupPolicyFields.bq_snapshot_storage_dataset.toString(), TagField.newBuilder().setStringValue(bigQuerySnapshotStorageDataset).build()); } // optional: gcs snapshot storage location if (gcsSnapshotStorageLocation != null) { - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.gcs_snapshot_storage_location.toString(), + tagBuilder.putFields(BackupPolicyFields.gcs_snapshot_storage_location.toString(), TagField.newBuilder().setStringValue(gcsSnapshotStorageLocation).build()); } // optional: gcs export format if (gcsExportFormat != null) { - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.gcs_snapshot_format.toString(), + tagBuilder.putFields(BackupPolicyFields.gcs_snapshot_format.toString(), TagField.newBuilder().setEnumValue( TagField.EnumValue.newBuilder().setDisplayName( gcsExportFormat.toString()) @@ -317,36 +342,36 @@ public Tag toDataCatalogTag(String tagTemplateId, String tagName) { // optional: gcs csv field delimiter if (gcsCsvDelimiter != null) { tagBuilder.putFields( - DataCatalogBackupPolicyTagFields.gcs_csv_delimiter.toString(), + BackupPolicyFields.gcs_csv_delimiter.toString(), TagField.newBuilder().setStringValue(gcsCsvDelimiter).build()); } // optional: gcs_csv_export_header if (gcsCsvExportHeader != null) { tagBuilder.putFields( - DataCatalogBackupPolicyTagFields.gcs_csv_export_header.toString(), + BackupPolicyFields.gcs_csv_export_header.toString(), TagField.newBuilder().setBoolValue(gcsCsvExportHeader).build()); } // optional: gcs csv field delimiter if (gcsUseAvroLogicalTypes != null) { tagBuilder.putFields( - DataCatalogBackupPolicyTagFields.gcs_avro_use_logical_types.toString(), + BackupPolicyFields.gcs_avro_use_logical_types.toString(), TagField.newBuilder().setBoolValue(gcsUseAvroLogicalTypes).build()); } // required: config source - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.config_source.toString(), + tagBuilder.putFields(BackupPolicyFields.config_source.toString(), TagField.newBuilder().setEnumValue( - TagField.EnumValue.newBuilder().setDisplayName( - configSource.toString()) - .build()) - .build()); + TagField.EnumValue.newBuilder().setDisplayName( + configSource.toString()) + .build()) + .build()); // optional: last backup at if (lastBackupAt != null) { - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.last_backup_at.toString(), + tagBuilder.putFields(BackupPolicyFields.last_backup_at.toString(), TagField.newBuilder().setTimestampValue( com.google.protobuf.Timestamp.newBuilder() .setSeconds(lastBackupAt.getSeconds()) @@ -358,13 +383,13 @@ public Tag toDataCatalogTag(String tagTemplateId, String tagName) { // optional: last bq snapshot uri if (lastBqSnapshotStorageUri != null) { - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.last_bq_snapshot_storage_uri.toString(), + tagBuilder.putFields(BackupPolicyFields.last_bq_snapshot_storage_uri.toString(), TagField.newBuilder().setStringValue(lastBqSnapshotStorageUri).build()); } // optional: last gcs snapshot uri if (lastGcsSnapshotStorageUri != null) { - tagBuilder.putFields(DataCatalogBackupPolicyTagFields.last_gcs_snapshot_storage_uri.toString(), + tagBuilder.putFields(BackupPolicyFields.last_gcs_snapshot_storage_uri.toString(), TagField.newBuilder().setStringValue(lastGcsSnapshotStorageUri).build()); } @@ -375,27 +400,142 @@ public Tag toDataCatalogTag(String tagTemplateId, String tagName) { return tagBuilder.build(); } + public Entity toFireStoreEntity(Key entityKey) { + + // build required fields + Entity.Builder builder = Entity.newBuilder(entityKey) + .set(BackupPolicyFields.backup_cron.toString(), this.getCron()) + .set(BackupPolicyFields.backup_method.toString(), this.getMethod().getText()) + .set(BackupPolicyFields.backup_time_travel_offset_days.toString(), this.getTimeTravelOffsetDays().getText()) + .set(BackupPolicyFields.config_source.toString(), this.getConfigSource().getText()) + .set(BackupPolicyFields.backup_storage_project.toString(), this.getBackupStorageProject()); + + if(this.getBackupOperationProject() != null){ + builder.set(BackupPolicyFields.backup_operation_project.toString(), this.getBackupOperationProject()); + } + + if(this.getBigQuerySnapshotExpirationDays() != null){ + builder.set(BackupPolicyFields.bq_snapshot_expiration_days.toString(), this.getBigQuerySnapshotExpirationDays()); + } + + if(this.getBigQuerySnapshotStorageDataset() != null){ + builder.set(BackupPolicyFields.bq_snapshot_storage_dataset.toString(), this.getBigQuerySnapshotStorageDataset()); + } + + if(this.getGcsSnapshotStorageLocation() != null){ + builder.set(BackupPolicyFields.gcs_snapshot_storage_location.toString(), this.getGcsSnapshotStorageLocation()); + } + + if(this.getGcsExportFormat() != null){ + builder.set(BackupPolicyFields.gcs_snapshot_format.toString(), this.getGcsExportFormat().toString()); + } + + if(this.getGcsCsvDelimiter() != null){ + builder.set(BackupPolicyFields.gcs_csv_delimiter.toString(), this.getGcsCsvDelimiter()); + } + + if(this.getGcsCsvExportHeader() != null){ + builder.set(BackupPolicyFields.gcs_csv_export_header.toString(), this.getGcsCsvExportHeader()); + } + + if(this.getGcsUseAvroLogicalTypes() != null){ + builder.set(BackupPolicyFields.gcs_avro_use_logical_types.toString(), this.getGcsUseAvroLogicalTypes()); + } + + if(this.getLastBackupAt() != null){ + builder.set(BackupPolicyFields.last_backup_at.toString(), this.getLastBackupAt()); + } + + if(this.getLastBqSnapshotStorageUri() != null){ + builder.set(BackupPolicyFields.last_bq_snapshot_storage_uri.toString(), this.getLastBqSnapshotStorageUri()); + } + + if(this.getLastGcsSnapshotStorageUri() != null){ + builder.set(BackupPolicyFields.last_gcs_snapshot_storage_uri.toString(), this.getLastGcsSnapshotStorageUri()); + } + + return builder.build(); + } + + public Map toMap(){ + Map fields = new HashMap<>(); + // required fields + fields.put(BackupPolicyFields.backup_cron.toString(), cron); + fields.put(BackupPolicyFields.backup_method.toString(), method.getText()); + fields.put(BackupPolicyFields.backup_time_travel_offset_days.toString(), timeTravelOffsetDays.getText()); + fields.put(BackupPolicyFields.backup_storage_project.toString(), backupStorageProject); + fields.put(BackupPolicyFields.config_source.toString(), configSource.getText()); + fields.put(BackupPolicyFields.backup_storage_project.toString(), backupStorageProject); + fields.put(BackupPolicyFields.config_source.toString(), configSource.getText()); + + // optional fields + if(this.getBackupOperationProject() != null){ + fields.put(BackupPolicyFields.backup_operation_project.toString(), this.getBackupOperationProject()); + } + + if(this.getBigQuerySnapshotExpirationDays() != null){ + fields.put(BackupPolicyFields.bq_snapshot_expiration_days.toString(), this.getBigQuerySnapshotExpirationDays().toString()); + } + + if(this.getBigQuerySnapshotStorageDataset() != null){ + fields.put(BackupPolicyFields.bq_snapshot_storage_dataset.toString(), this.getBigQuerySnapshotStorageDataset()); + } + + if(this.getGcsSnapshotStorageLocation() != null){ + fields.put(BackupPolicyFields.gcs_snapshot_storage_location.toString(), this.getGcsSnapshotStorageLocation()); + } + + if(this.getGcsExportFormat() != null){ + fields.put(BackupPolicyFields.gcs_snapshot_format.toString(), this.getGcsExportFormat().toString()); + } + + if(this.getGcsCsvDelimiter() != null){ + fields.put(BackupPolicyFields.gcs_csv_delimiter.toString(), this.getGcsCsvDelimiter()); + } + + if(this.getGcsCsvExportHeader() != null){ + fields.put(BackupPolicyFields.gcs_csv_export_header.toString(), this.getGcsCsvExportHeader().toString()); + } + + if(this.getGcsUseAvroLogicalTypes() != null){ + fields.put(BackupPolicyFields.gcs_avro_use_logical_types.toString(), this.getGcsUseAvroLogicalTypes().toString()); + } + + if(this.getLastBackupAt() != null){ + fields.put(BackupPolicyFields.last_backup_at.toString(), this.getLastBackupAt().toString()); + } + + if(this.getLastBqSnapshotStorageUri() != null){ + fields.put(BackupPolicyFields.last_bq_snapshot_storage_uri.toString(), this.getLastBqSnapshotStorageUri()); + } + + if(this.getLastGcsSnapshotStorageUri() != null){ + fields.put(BackupPolicyFields.last_gcs_snapshot_storage_uri.toString(), this.getLastGcsSnapshotStorageUri()); + } + + return fields; + } // used to parse from json map (fallback policies) or data catalog tags (backup policies) - public static BackupPolicy fromMap(Map tagTemplate) throws IllegalArgumentException { + public static BackupPolicy fromMap(Map fieldsMap) throws IllegalArgumentException { // parse required fields - String cron = Utils.getOrFail(tagTemplate, DataCatalogBackupPolicyTagFields.backup_cron.toString()); + String cron = Utils.getOrFail(fieldsMap, BackupPolicyFields.backup_cron.toString()); BackupMethod method = BackupMethod.fromString( - Utils.getOrFail(tagTemplate, DataCatalogBackupPolicyTagFields.backup_method.toString()) + Utils.getOrFail(fieldsMap, BackupPolicyFields.backup_method.toString()) ); TimeTravelOffsetDays timeTravelOffsetDays = TimeTravelOffsetDays.fromString( - Utils.getOrFail(tagTemplate, DataCatalogBackupPolicyTagFields.backup_time_travel_offset_days.toString()) + Utils.getOrFail(fieldsMap, BackupPolicyFields.backup_time_travel_offset_days.toString()) ); - String backupStorageProject = Utils.getOrFail(tagTemplate, DataCatalogBackupPolicyTagFields.backup_storage_project.toString()); + String backupStorageProject = Utils.getOrFail(fieldsMap, BackupPolicyFields.backup_storage_project.toString()); // config source is not required in the fallback policies. It defaults to SYSTEM if not present - String configSourceStr = tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.config_source.toString(), + String configSourceStr = fieldsMap.getOrDefault( + BackupPolicyFields.config_source.toString(), null); BackupConfigSource configSource = configSourceStr == null ? BackupConfigSource.SYSTEM : BackupConfigSource.fromString(configSourceStr); @@ -406,83 +546,83 @@ public static BackupPolicy fromMap(Map tagTemplate) throws Illeg // these fields might not exist in the attached tag template if not filled. Same for fallback policies backupPolicyBuilder.setBackupOperationProject( - tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.backup_operation_project.toString(), + fieldsMap.getOrDefault( + BackupPolicyFields.backup_operation_project.toString(), null ) ); backupPolicyBuilder.setBigQuerySnapshotStorageDataset( - tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.bq_snapshot_storage_dataset.toString(), + fieldsMap.getOrDefault( + BackupPolicyFields.bq_snapshot_storage_dataset.toString(), null) ); - String bqSnapshotExpirationDaysStr = tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.bq_snapshot_expiration_days.toString(), + String bqSnapshotExpirationDaysStr = fieldsMap.getOrDefault( + BackupPolicyFields.bq_snapshot_expiration_days.toString(), null); backupPolicyBuilder.setBigQuerySnapshotExpirationDays( - bqSnapshotExpirationDaysStr == null? null: Double.parseDouble(bqSnapshotExpirationDaysStr) + bqSnapshotExpirationDaysStr == null ? null : Double.parseDouble(bqSnapshotExpirationDaysStr) ); // parse optional GCS snapshot settings backupPolicyBuilder.setGcsSnapshotStorageLocation( - tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.gcs_snapshot_storage_location.toString(), + fieldsMap.getOrDefault( + BackupPolicyFields.gcs_snapshot_storage_location.toString(), null) ); - String gcsSnapshotFormatStr = tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.gcs_snapshot_format.toString(), + String gcsSnapshotFormatStr = fieldsMap.getOrDefault( + BackupPolicyFields.gcs_snapshot_format.toString(), null); backupPolicyBuilder.setGcsExportFormat( - gcsSnapshotFormatStr == null? null: GCSSnapshotFormat.valueOf(gcsSnapshotFormatStr) + gcsSnapshotFormatStr == null ? null : GCSSnapshotFormat.valueOf(gcsSnapshotFormatStr) ); backupPolicyBuilder.setGcsCsvDelimiter( - tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.gcs_csv_delimiter.toString(), + fieldsMap.getOrDefault( + BackupPolicyFields.gcs_csv_delimiter.toString(), null) ); // if optional boolean values are not provided, set them to null and not false - String gcsCsvExportHeaderStr = tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.gcs_csv_export_header.toString(), + String gcsCsvExportHeaderStr = fieldsMap.getOrDefault( + BackupPolicyFields.gcs_csv_export_header.toString(), null); backupPolicyBuilder.setGcsCsvExportHeader( - gcsCsvExportHeaderStr == null? null: Boolean.valueOf(gcsCsvExportHeaderStr) + gcsCsvExportHeaderStr == null ? null : Boolean.valueOf(gcsCsvExportHeaderStr) ); // if optional boolean values are not provided, set them to null and not false - String gcsAvroUseLogicalAvroTypeStr = tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.gcs_avro_use_logical_types.toString(), + String gcsAvroUseLogicalAvroTypeStr = fieldsMap.getOrDefault( + BackupPolicyFields.gcs_avro_use_logical_types.toString(), null); backupPolicyBuilder.setGcsUseAvroLogicalTypes( - gcsAvroUseLogicalAvroTypeStr == null? null: Boolean.valueOf(gcsAvroUseLogicalAvroTypeStr) + gcsAvroUseLogicalAvroTypeStr == null ? null : Boolean.valueOf(gcsAvroUseLogicalAvroTypeStr) ); - String lastBackupAtStr = tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.last_backup_at.toString(), + String lastBackupAtStr = fieldsMap.getOrDefault( + BackupPolicyFields.last_backup_at.toString(), null); backupPolicyBuilder.setLastBackupAt( lastBackupAtStr == null ? null : Timestamp.parseTimestamp(lastBackupAtStr) ); backupPolicyBuilder.setLastBqSnapshotStorageUri( - tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.last_bq_snapshot_storage_uri.toString(), + fieldsMap.getOrDefault( + BackupPolicyFields.last_bq_snapshot_storage_uri.toString(), null) ); - backupPolicyBuilder.setLastGcsSnapshotStorageUri(tagTemplate.getOrDefault( - DataCatalogBackupPolicyTagFields.last_gcs_snapshot_storage_uri.toString(), + backupPolicyBuilder.setLastGcsSnapshotStorageUri(fieldsMap.getOrDefault( + BackupPolicyFields.last_gcs_snapshot_storage_uri.toString(), null)); return backupPolicyBuilder.build(); } - public static class BackupPolicyBuilder{ + public static class BackupPolicyBuilder { // required private String cron; @@ -508,7 +648,7 @@ public static class BackupPolicyBuilder{ private String lastBqSnapshotStorageUri; private String lastGcsSnapshotStorageUri; - public static BackupPolicyBuilder from(BackupPolicy backupPolicy){ + public static BackupPolicyBuilder from(BackupPolicy backupPolicy) { return new BackupPolicyBuilder( backupPolicy.cron, backupPolicy.method, @@ -528,7 +668,7 @@ public static BackupPolicyBuilder from(BackupPolicy backupPolicy){ .setLastGcsSnapshotStorageUri(backupPolicy.lastGcsSnapshotStorageUri); } - public BackupPolicyBuilder(String cron, BackupMethod method, TimeTravelOffsetDays timeTravelOffsetDays, BackupConfigSource configSource, String backupStorageProject){ + public BackupPolicyBuilder(String cron, BackupMethod method, TimeTravelOffsetDays timeTravelOffsetDays, BackupConfigSource configSource, String backupStorageProject) { this.cron = cron; this.method = method; this.timeTravelOffsetDays = timeTravelOffsetDays; @@ -551,7 +691,7 @@ public BackupPolicyBuilder setLastGcsSnapshotStorageUri(String lastGcsSnapshotSt return this; } - public BackupPolicyBuilder setBackupOperationProject(String backupOperationProject) { + public BackupPolicyBuilder setBackupOperationProject(String backupOperationProject) { this.backupOperationProject = backupOperationProject; return this; } @@ -616,7 +756,7 @@ public BackupPolicyBuilder setGcsUseAvroLogicalTypes(Boolean gcsUseAvroLogicalTy return this; } - public BackupPolicy build(){ + public BackupPolicy build() { return new BackupPolicy(this); } } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/DataCatalogBackupPolicyTagFields.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/BackupPolicyFields.java similarity index 82% rename from services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/DataCatalogBackupPolicyTagFields.java rename to services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/BackupPolicyFields.java index 2cdb1df..2441781 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/DataCatalogBackupPolicyTagFields.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/entities/backup_policy/BackupPolicyFields.java @@ -1,6 +1,7 @@ package com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy; -public enum DataCatalogBackupPolicyTagFields { +// Field names used to represent a backup policy on external storage layer(s) +public enum BackupPolicyFields { backup_cron, backup_method, backup_time_travel_offset_days, diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/Dispatcher.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/Dispatcher.java index 5239e83..07ef336 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/Dispatcher.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/Dispatcher.java @@ -66,7 +66,8 @@ public Dispatcher(DispatcherConfig config, logger = new LoggingHelper( Dispatcher.class.getSimpleName(), functionNumber, - config.getProjectId() + config.getProjectId(), + config.getApplicationName() ); } @@ -96,7 +97,8 @@ public PubSubPublishResults execute(DispatcherRequest dispatcherRequest, String new LoggingHelper( BigQueryScopeLister.class.getSimpleName(), functionNumber, - config.getProjectId() + config.getProjectId(), + config.getApplicationName() ), runId ); diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherConfig.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherConfig.java index b709a01..0c66af1 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherConfig.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherConfig.java @@ -23,15 +23,19 @@ public class DispatcherConfig { private String dataRegionId; private String outputTopic; + private String applicationName; + public DispatcherConfig(String projectId, String computeRegionId, String dataRegionId, - String outputTopic + String outputTopic, + String applicationName ) { this.projectId = projectId; this.computeRegionId = computeRegionId; this.dataRegionId = dataRegionId; this.outputTopic = outputTopic; + this.applicationName = applicationName; } public String getDataRegionId() { @@ -50,6 +54,9 @@ public String getOutputTopic() { return outputTopic; } + public String getApplicationName() { + return applicationName; + } @Override public String toString() { @@ -58,6 +65,7 @@ public String toString() { ", computeRegionId='" + computeRegionId + '\'' + ", dataRegionId='" + dataRegionId + '\'' + ", outputTopic='" + outputTopic + '\'' + + ", applicationName='" + applicationName + '\'' + '}'; } } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/Configurator.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/Configurator.java index 4f1b984..4b31f96 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/Configurator.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/Configurator.java @@ -11,10 +11,9 @@ import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.FallbackBackupPolicy; import com.google.cloud.pso.bq_snapshot_manager.functions.f03_snapshoter.SnapshoterRequest; import com.google.cloud.pso.bq_snapshot_manager.helpers.LoggingHelper; -import com.google.cloud.pso.bq_snapshot_manager.helpers.TrackingHelper; import com.google.cloud.pso.bq_snapshot_manager.helpers.Utils; import com.google.cloud.pso.bq_snapshot_manager.services.bq.BigQueryService; -import com.google.cloud.pso.bq_snapshot_manager.services.catalog.DataCatalogService; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyService; import com.google.cloud.pso.bq_snapshot_manager.services.pubsub.PubSubPublishResults; import com.google.cloud.pso.bq_snapshot_manager.services.pubsub.PubSubService; import com.google.cloud.pso.bq_snapshot_manager.services.set.PersistentSet; @@ -34,7 +33,7 @@ public class Configurator { private final BigQueryService bqService; - private final DataCatalogService dataCatalogService; + private final BackupPolicyService backupPolicyService; private final PubSubService pubSubService; private final PersistentSet persistentSet; private final FallbackBackupPolicy fallbackBackupPolicy; @@ -43,7 +42,7 @@ public class Configurator { public Configurator(ConfiguratorConfig config, BigQueryService bqService, - DataCatalogService dataCatalogService, + BackupPolicyService backupPolicyService, PubSubService pubSubService, PersistentSet persistentSet, FallbackBackupPolicy fallbackBackupPolicy, @@ -51,7 +50,7 @@ public Configurator(ConfiguratorConfig config, Integer functionNumber) { this.config = config; this.bqService = bqService; - this.dataCatalogService = dataCatalogService; + this.backupPolicyService = backupPolicyService; this.pubSubService = pubSubService; this.persistentSet = persistentSet; this.fallbackBackupPolicy = fallbackBackupPolicy; @@ -61,7 +60,8 @@ public Configurator(ConfiguratorConfig config, logger = new LoggingHelper( Configurator.class.getSimpleName(), functionNumber, - config.getProjectId() + config.getProjectId(), + config.getApplicationName() ); } @@ -218,16 +218,28 @@ public ConfiguratorResponse execute(ConfiguratorRequest request, String pubSubMe public BackupPolicy getBackupPolicy(ConfiguratorRequest request) throws IOException { // Check if the table has a back policy attached to it in data catalog - BackupPolicy attachedBackupPolicy = dataCatalogService.getBackupPolicyTag( - request.getTargetTable(), - config.getBackupTagTemplateId() + BackupPolicy attachedBackupPolicy = backupPolicyService.getBackupPolicyForTable( + request.getTargetTable() ); // if there is manually attached backup policy (e.g. by the table designer) then use it. if (attachedBackupPolicy != null && attachedBackupPolicy.getConfigSource().equals(BackupConfigSource.MANUAL)) { + + logger.logInfoWithTracker(request.isDryRun(), + request.getTrackingId(), + request.getTargetTable(), + String.format("Attached backup policy found for table %s", request.getTargetTable()) + ); + return attachedBackupPolicy; }else{ + logger.logInfoWithTracker(request.isDryRun(), + request.getTrackingId(), + request.getTargetTable(), + String.format("No 'config_source=MANUAL' backup policy found for table %s. Will search for a fallback policy.", request.getTargetTable()) + ); + // find the most granular fallback policy table > dataset > project BackupPolicy fallbackPolicy = findFallbackBackupPolicy(fallbackBackupPolicy, request.getTargetTable()).y(); diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorConfig.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorConfig.java index fcd3e65..a460a2b 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorConfig.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorConfig.java @@ -7,14 +7,19 @@ public class ConfiguratorConfig { private final String gcsSnapshoterTopic; private final String backupTagTemplateId; + private final String applicationName; + public ConfiguratorConfig(String projectId, String bigQuerySnapshoterTopic, String gcsSnapshoterTopic, - String backupTagTemplateId) { + String backupTagTemplateId, + String applicationName + ) { this.projectId = projectId; this.bigQuerySnapshoterTopic = bigQuerySnapshoterTopic; this.gcsSnapshoterTopic = gcsSnapshoterTopic; this.backupTagTemplateId = backupTagTemplateId; + this.applicationName = applicationName; } public String getProjectId() { @@ -33,6 +38,10 @@ public String getBackupTagTemplateId() { return backupTagTemplateId; } + public String getApplicationName() { + return applicationName; + } + @Override public String toString() { return "ConfiguratorConfig{" + @@ -40,6 +49,7 @@ public String toString() { ", bigQuerySnapshoterTopic='" + bigQuerySnapshoterTopic + '\'' + ", gcsSnapshoterTopic='" + gcsSnapshoterTopic + '\'' + ", backupTagTemplateId='" + backupTagTemplateId + '\'' + + ", applicationName='" + applicationName + '\'' + '}'; } } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoter.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoter.java index c9db13b..009a920 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoter.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoter.java @@ -63,7 +63,8 @@ public BigQuerySnapshoter(SnapshoterConfig config, logger = new LoggingHelper( BigQuerySnapshoter.class.getSimpleName(), functionNumber, - config.getProjectId() + config.getProjectId(), + config.getApplicationName() ); } @@ -139,7 +140,7 @@ public BigQuerySnapshoterResponse execute(SnapshoterRequest request, Timestamp o if(!request.isDryRun()){ - String jobId = TrackingHelper.generateBQSnapshotJobId(request.getTrackingId()); + String jobId = TrackingHelper.generateBQSnapshotJobId(request.getTrackingId(), config.getApplicationName()); // API Call bqService.createSnapshot( diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoter.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoter.java index 95b1c5b..caf0c5f 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoter.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoter.java @@ -2,7 +2,6 @@ import com.google.cloud.Timestamp; import com.google.cloud.Tuple; -import com.google.cloud.pso.bq_snapshot_manager.entities.Globals; import com.google.cloud.pso.bq_snapshot_manager.entities.NonRetryableApplicationException; import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupMethod; @@ -53,7 +52,8 @@ public GCSSnapshoter(SnapshoterConfig config, logger = new LoggingHelper( GCSSnapshoter.class.getSimpleName(), functionNumber, - config.getProjectId() + config.getProjectId(), + config.getApplicationName() ); } @@ -130,7 +130,7 @@ public GCSSnapshoterResponse execute(SnapshoterRequest request, Timestamp operat if(!request.isDryRun()){ // create an async bq export job - String jobId = TrackingHelper.generateBQExportJobId(request.getTrackingId()); + String jobId = TrackingHelper.generateBQExportJobId(request.getTrackingId(), config.getApplicationName()); // We create the tagging request and added it to a persistent storage // The Tagger service will receive notifications of export job completion via log sinks and pick up the tagger request from the persistent storage @@ -152,7 +152,7 @@ public GCSSnapshoterResponse execute(SnapshoterRequest request, Timestamp operat Map jobLabels = new HashMap<>(); // labels has to be max 63 chars, contain only lowercase letters, numeric characters, underscores, and dashes. All characters must use UTF-8 encoding, and international characters are allowed. - jobLabels.put("app", Globals.APPLICATION_NAME); + jobLabels.put("app", config.getApplicationName()); // API Call bqService.exportToGCS( diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/SnapshoterConfig.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/SnapshoterConfig.java index 66be11f..885fe22 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/SnapshoterConfig.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/SnapshoterConfig.java @@ -21,9 +21,12 @@ public class SnapshoterConfig { private String projectId; private String outputTopic; - public SnapshoterConfig(String projectId, String outputTopic) { + private String applicationName; + + public SnapshoterConfig(String projectId, String outputTopic, String applicationName) { this.projectId = projectId; this.outputTopic = outputTopic; + this.applicationName = applicationName; } public String getProjectId() { @@ -34,11 +37,16 @@ public String getOutputTopic() { return outputTopic; } + public String getApplicationName() { + return applicationName; + } + @Override public String toString() { return "SnapshoterConfig{" + "projectId='" + projectId + '\'' + ", outputTopic='" + outputTopic + '\'' + + ", applicationName='" + applicationName + '\'' + '}'; } } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/Tagger.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/Tagger.java index bd55a28..5b37be9 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/Tagger.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/Tagger.java @@ -20,26 +20,38 @@ import com.google.cloud.pso.bq_snapshot_manager.entities.RetryableApplicationException; import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupMethod; import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupPolicy; +import com.google.cloud.pso.bq_snapshot_manager.functions.f03_snapshoter.GCSSnapshoter; import com.google.cloud.pso.bq_snapshot_manager.helpers.LoggingHelper; import com.google.cloud.pso.bq_snapshot_manager.helpers.Utils; -import com.google.cloud.pso.bq_snapshot_manager.services.catalog.DataCatalogService; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyService; import com.google.cloud.pso.bq_snapshot_manager.services.set.PersistentSet; +import java.io.IOException; + public class Tagger { private final LoggingHelper logger; private final TaggerConfig config; - private final DataCatalogService dataCatalogService; + private final BackupPolicyService backupPolicyService; private final PersistentSet persistentSet; private final String persistentSetObjectPrefix; - public Tagger(LoggingHelper logger, TaggerConfig config, DataCatalogService dataCatalogService, PersistentSet persistentSet, String persistentSetObjectPrefix) { - this.logger = logger; + private final Integer functionNumber; + + public Tagger(TaggerConfig config, BackupPolicyService backupPolicyService, PersistentSet persistentSet, String persistentSetObjectPrefix, Integer functionNumber) { this.config = config; - this.dataCatalogService = dataCatalogService; + this.backupPolicyService = backupPolicyService; this.persistentSet = persistentSet; this.persistentSetObjectPrefix = persistentSetObjectPrefix; + this.functionNumber = functionNumber; + + logger = new LoggingHelper( + Tagger.class.getSimpleName(), + functionNumber, + config.getProjectId(), + config.getApplicationName() + ); } /** @@ -52,7 +64,7 @@ public Tagger(LoggingHelper logger, TaggerConfig config, DataCatalogService data public TaggerResponse execute( TaggerRequest request, String pubSubMessageId - ) throws NonRetryableApplicationException, RetryableApplicationException { + ) throws NonRetryableApplicationException, RetryableApplicationException, IOException { // run common service start logging and checks Utils.runServiceStartRoutines( @@ -99,10 +111,9 @@ public TaggerResponse execute( if(!request.isDryRun()){ // update the tag // API Calls - dataCatalogService.createOrUpdateBackupPolicyTag( + backupPolicyService.createOrUpdateBackupPolicyForTable( request.getTargetTable(), - upDatedBackupPolicy, - config.getTagTemplateId() + upDatedBackupPolicy ); } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/TaggerConfig.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/TaggerConfig.java index 488120d..0490697 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/TaggerConfig.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/functions/f04_tagger/TaggerConfig.java @@ -18,13 +18,18 @@ public class TaggerConfig { - private String projectId; - private String tagTemplateId; + private final String projectId; + private final String tagTemplateId; + + private final String applicationName; public TaggerConfig(String projectId, - String tagTemplateId) { + String tagTemplateId, + String applicationName + ) { this.projectId = projectId; this.tagTemplateId = tagTemplateId; + this.applicationName = applicationName; } public String getProjectId() { @@ -35,11 +40,16 @@ public String getTagTemplateId() { return tagTemplateId; } + public String getApplicationName() { + return applicationName; + } + @Override public String toString() { return "TaggerConfig{" + "projectId='" + projectId + '\'' + ", tagTemplateId='" + tagTemplateId + '\'' + + ", applicationName='" + applicationName + '\'' + '}'; } } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/LoggingHelper.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/LoggingHelper.java index 19dcb20..02e984f 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/LoggingHelper.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/LoggingHelper.java @@ -37,10 +37,13 @@ public class LoggingHelper { // Used to create a trace private final String projectId; - public LoggingHelper(String loggerName, Integer functionNumber, String projectId) { + private final String applicationName; + + public LoggingHelper(String loggerName, Integer functionNumber, String projectId, String applicationName) { this.loggerName = loggerName; this.functionNumber = functionNumber; this.projectId = projectId; + this.applicationName = applicationName; logger = LoggerFactory.getLogger(loggerName); } @@ -257,7 +260,7 @@ private void logWithTracker(ApplicationLog log, Boolean isDryRun, String tracker // Enable JSON logging with Logback and SLF4J by enabling the Logstash JSON Encoder in your logback.xml configuration. String payload = String.format("%s | %s | %s | %s | %s | %s", - Globals.APPLICATION_NAME, + applicationName, log, loggerName, isDryRun!=null? (isDryRun?"Dry-Run":"Wet-Run") : null, @@ -274,7 +277,7 @@ private void logWithTracker(ApplicationLog log, Boolean isDryRun, String tracker } Object [] globalAttributes = new Object[]{ - kv("global_app", Globals.APPLICATION_NAME), + kv("global_app", applicationName), kv("global_logger_name", this.loggerName), kv("global_app_log", log), kv("global_tracker", tracker), diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelper.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelper.java index 955dc25..0b0b744 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelper.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelper.java @@ -17,7 +17,6 @@ package com.google.cloud.pso.bq_snapshot_manager.helpers; import com.google.cloud.Timestamp; -import com.google.cloud.pso.bq_snapshot_manager.entities.Globals; import java.util.UUID; @@ -70,16 +69,16 @@ public static String generateTrackingId (String runId){ return String.format("%s-%s", runId, UUID.randomUUID().toString()); } - public static String generateBQExportJobId(String trackingId){ - return String.format("%s_%s_%s",trackingId, "export", Globals.APPLICATION_NAME, trackingId); + public static String generateBQExportJobId(String trackingId, String applicationName){ + return String.format("%s_%s_%s",trackingId, "export", applicationName, trackingId); } public static String parseTrackingIdFromBQExportJobId(String bqExportJobId){ return Utils.tokenize(bqExportJobId,"_", true).get(0); } - public static String generateBQSnapshotJobId(String trackingId){ - return String.format("%s_%s_%s",trackingId, "snapshot", Globals.APPLICATION_NAME, trackingId); + public static String generateBQSnapshotJobId(String trackingId, String applicationName){ + return String.format("%s_%s_%s",trackingId, "snapshot", applicationName, trackingId); } } diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/Utils.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/Utils.java index f01d9e7..b4f1154 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/Utils.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/Utils.java @@ -142,8 +142,8 @@ public static Tuple getTableSpecWithTimeTravel(TableSpec table, // always use time travel for consistency and traceability timeTravelMs = refPointMs; }else{ - // use a buffer (milliseconds) to count for the operation time - Long bufferMs = timeTravelOffsetDays.equals(TimeTravelOffsetDays.DAYS_7) ? 60000L : 0L; + // use a buffer (milliseconds) to count for the operation time. 1 MIN = 60000 MILLISECONDS + Long bufferMs = timeTravelOffsetDays.equals(TimeTravelOffsetDays.DAYS_7) ? 60 * 60000L : 0L; // milli seconds per day * number of days Long timeTravelOffsetMs = (86400000L * Long.parseLong(timeTravelOffsetDays.getText())); timeTravelMs = (refPointMs - timeTravelOffsetMs) + bufferMs; diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyService.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyService.java new file mode 100644 index 0000000..901ae02 --- /dev/null +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyService.java @@ -0,0 +1,16 @@ +package com.google.cloud.pso.bq_snapshot_manager.services.backup_policy; + +import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupPolicy; +import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; + +import javax.annotation.Nullable; +import java.io.IOException; + +public interface BackupPolicyService { + + void createOrUpdateBackupPolicyForTable(TableSpec tableSpec, BackupPolicy backupPolicy) throws IOException; + + @Nullable BackupPolicy getBackupPolicyForTable(TableSpec tableSpec) throws IOException, IllegalArgumentException; + + void shutdown(); +} diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/catalog/DataCatalogServiceImpl.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceDataCatalogImpl.java similarity index 67% rename from services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/catalog/DataCatalogServiceImpl.java rename to services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceDataCatalogImpl.java index bab4879..4dcfad0 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/catalog/DataCatalogServiceImpl.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceDataCatalogImpl.java @@ -1,4 +1,4 @@ -package com.google.cloud.pso.bq_snapshot_manager.services.catalog; +package com.google.cloud.pso.bq_snapshot_manager.services.backup_policy; import com.google.cloud.Timestamp; @@ -14,19 +14,21 @@ import java.util.Map; import java.util.stream.Collectors; -public class DataCatalogServiceImpl implements DataCatalogService { +public class BackupPolicyServiceDataCatalogImpl implements BackupPolicyService { private final DataCatalogClient dataCatalogClient; + private String backupPolicyTagTemplateId; - public DataCatalogServiceImpl() throws IOException { + public BackupPolicyServiceDataCatalogImpl(String backupPolicyTagTemplateId) throws IOException { dataCatalogClient = DataCatalogClient.create(); + this.backupPolicyTagTemplateId = backupPolicyTagTemplateId; } - public void shutdown(){ + public void shutdown() { dataCatalogClient.shutdown(); } - public Tag createOrUpdateBackupPolicyTag(TableSpec tableSpec, BackupPolicy backupPolicy, String backupPolicyTagTemplateId){ + public void createOrUpdateBackupPolicyForTable(TableSpec tableSpec, BackupPolicy backupPolicy) { // API Call String parent = getBigQueryEntryName(tableSpec); @@ -35,7 +37,7 @@ public Tag createOrUpdateBackupPolicyTag(TableSpec tableSpec, BackupPolicy backu DataCatalogClient.ListTagsPagedResponse response = dataCatalogClient.listTags(parent); List allTags = new ArrayList<>(); - for (DataCatalogClient.ListTagsPage l: response.iteratePages()){ + for (DataCatalogClient.ListTagsPage l : response.iteratePages()) { allTags.addAll(l.getResponse().getTagsList()); } @@ -44,12 +46,12 @@ public Tag createOrUpdateBackupPolicyTag(TableSpec tableSpec, BackupPolicy backu backupPolicyTagTemplateId ); - if(tag == null){ + if (tag == null) { // create a new tag - return dataCatalogClient.createTag(parent, backupPolicy.toDataCatalogTag(backupPolicyTagTemplateId, null)); - }else{ + dataCatalogClient.createTag(parent, backupPolicy.toDataCatalogTag(backupPolicyTagTemplateId, null)); + } else { // update existing tag referencing the existing tag.name - return dataCatalogClient.updateTag( + dataCatalogClient.updateTag( backupPolicy.toDataCatalogTag( backupPolicyTagTemplateId, tag.getName() @@ -58,13 +60,13 @@ public Tag createOrUpdateBackupPolicyTag(TableSpec tableSpec, BackupPolicy backu } } - public Tag findTag(List tags, String tagTemplateName){ + public Tag findTag(List tags, String tagTemplateName) { List foundTags = tags.stream().filter(t -> t.getTemplate().equals(tagTemplateName)) .collect(Collectors.toList()); // if more than one tag is found use the first one - return foundTags.size() >= 1? foundTags.get(0): null; + return foundTags.size() >= 1 ? foundTags.get(0) : null; } @@ -72,23 +74,22 @@ public Tag findTag(List tags, String tagTemplateName){ * Return the attached backup policy tag template or null if no template is attached * * @param tableSpec - * @param backupPolicyTagTemplateId * @return * @throws IllegalArgumentException */ - public @Nullable BackupPolicy getBackupPolicyTag(TableSpec tableSpec, String backupPolicyTagTemplateId) throws IllegalArgumentException { + public @Nullable BackupPolicy getBackupPolicyForTable(TableSpec tableSpec) throws IllegalArgumentException { Map tagTemplate = getTagFieldsMap(tableSpec, backupPolicyTagTemplateId); - if(tagTemplate == null){ + if (tagTemplate == null) { // no backup tag template is attached to this table return null; - }else{ + } else { return BackupPolicy.fromMap(convertTagFieldMapToStrMap(tagTemplate)); } } - public Tag getTag(TableSpec tableSpec, String templateId){ + public Tag getTag(TableSpec tableSpec, String templateId) { // API Call String parent = getBigQueryEntryName(tableSpec); // API CALL @@ -97,8 +98,8 @@ public Tag getTag(TableSpec tableSpec, String templateId){ // TODO: handle multiple pages List tags = response.getPage().getResponse().getTagsList(); - for (Tag tagTemplate: tags){ - if (tagTemplate.getTemplate().equals(templateId)){ + for (Tag tagTemplate : tags) { + if (tagTemplate.getTemplate().equals(templateId)) { return tagTemplate; } } @@ -108,10 +109,10 @@ public Tag getTag(TableSpec tableSpec, String templateId){ public Map getTagFieldsMap(TableSpec tableSpec, String templateId) { Tag tag = getTag(tableSpec, templateId); - return tag == null? null: tag.getFieldsMap(); + return tag == null ? null : tag.getFieldsMap(); } - public String getBigQueryEntryName(TableSpec tableSpec){ + public String getBigQueryEntryName(TableSpec tableSpec) { LookupEntryRequest lookupEntryRequest = LookupEntryRequest.newBuilder() .setLinkedResource(tableSpec.toDataCatalogLinkedResource()).build(); @@ -120,30 +121,30 @@ public String getBigQueryEntryName(TableSpec tableSpec){ return dataCatalogClient.lookupEntry(lookupEntryRequest).getName(); } - public static Map convertTagFieldMapToStrMap(Map tagFieldMap){ + public static Map convertTagFieldMapToStrMap(Map tagFieldMap) { Map strMap = new HashMap<>(tagFieldMap.size()); - for(Map.Entry entry: tagFieldMap.entrySet()){ + for (Map.Entry entry : tagFieldMap.entrySet()) { String strValue = ""; - if(entry.getValue().hasBoolValue()){ + if (entry.getValue().hasBoolValue()) { strValue = String.valueOf(entry.getValue().getBoolValue()); } - if(entry.getValue().hasStringValue()){ + if (entry.getValue().hasStringValue()) { strValue = entry.getValue().getStringValue(); } - if(entry.getValue().hasDoubleValue()){ + if (entry.getValue().hasDoubleValue()) { strValue = String.valueOf(entry.getValue().getDoubleValue()); } - if(entry.getValue().hasEnumValue()){ + if (entry.getValue().hasEnumValue()) { strValue = entry.getValue().getEnumValue().getDisplayName(); } - if(entry.getValue().hasTimestampValue()){ + if (entry.getValue().hasTimestampValue()) { strValue = Timestamp.ofTimeSecondsAndNanos( entry.getValue().getTimestampValue().getSeconds(), entry.getValue().getTimestampValue().getNanos() ).toString(); } - if(entry.getValue().hasRichtextValue()){ + if (entry.getValue().hasRichtextValue()) { strValue = entry.getValue().getRichtextValue(); } strMap.put(entry.getKey(), strValue); diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceFireStoreImpl.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceFireStoreImpl.java new file mode 100644 index 0000000..28ca117 --- /dev/null +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceFireStoreImpl.java @@ -0,0 +1,59 @@ +package com.google.cloud.pso.bq_snapshot_manager.services.backup_policy; + + + +import com.google.cloud.datastore.*; +import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; +import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.*; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; + +public class BackupPolicyServiceFireStoreImpl implements BackupPolicyService { + + + private static final String KIND = "BigQueryBackupPolicy"; + private Datastore datastore; + + public BackupPolicyServiceFireStoreImpl() { + datastore = DatastoreOptions.getDefaultInstance().getService(); + } + + + public void createOrUpdateBackupPolicyForTable(TableSpec tableSpec, BackupPolicy backupPolicy) { + + Key backupPolicyKey = datastore.newKeyFactory().setKind(KIND).newKey(tableSpec.toSqlString()); + Entity backupPolicyEntity = backupPolicy.toFireStoreEntity(backupPolicyKey); + datastore.put(backupPolicyEntity); + } + + + public @Nullable BackupPolicy getBackupPolicyForTable(TableSpec tableSpec) { + Key backupPolicyKey = datastore.newKeyFactory().setKind(KIND).newKey(tableSpec.toSqlString()); + Entity backupPolicyEntity = datastore.get(backupPolicyKey); + if(backupPolicyEntity == null){ + // table doesn't have a backup policy stored + return null; + }else{ + Map propertiesMap = entityToStrMap(backupPolicyEntity); + return BackupPolicy.fromMap(propertiesMap); + } + } + + @Override + public void shutdown() { + // do nothing + } + + public Map entityToStrMap (Entity entity){ + Map strMap = new HashMap<>(entity.getProperties().size()); + + for (String key: entity.getProperties().keySet()) { + strMap.put(key, entity.getValue(key).get().toString()); + } + return strMap; + } + + +} diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceGCSImpl.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceGCSImpl.java new file mode 100644 index 0000000..6bde510 --- /dev/null +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/backup_policy/BackupPolicyServiceGCSImpl.java @@ -0,0 +1,59 @@ +package com.google.cloud.pso.bq_snapshot_manager.services.backup_policy; + +import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; +import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupPolicy; +import com.google.cloud.storage.*; + +import javax.annotation.Nullable; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class BackupPolicyServiceGCSImpl implements BackupPolicyService { + + + private Storage storage; + private String bucketName; + + public BackupPolicyServiceGCSImpl(String bucketName) { + // Instantiates a client + this.storage = StorageOptions.getDefaultInstance().getService(); + this.bucketName = bucketName; + } + + + public void createOrUpdateBackupPolicyForTable(TableSpec tableSpec, BackupPolicy backupPolicy) throws IOException { + + String filePath = tableToGcsKey(tableSpec); + BlobId blobId = BlobId.of(bucketName, filePath); + BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build(); + + byte[] content = backupPolicy.toJson().getBytes(StandardCharsets.UTF_8); + storage.createFrom(blobInfo, new ByteArrayInputStream(content)); + } + + + public @Nullable BackupPolicy getBackupPolicyForTable(TableSpec tableSpec) { + String filePath = tableToGcsKey(tableSpec); + BlobId blobId = BlobId.of(bucketName, filePath); + Blob blob = storage.get(blobId); + if (blob == null) { + return null; + } else { + byte[] contentBytes = storage.readAllBytes(blobId); + String contentStr = new String(contentBytes, StandardCharsets.UTF_8); + return BackupPolicy.fromJson(contentStr); + } + } + + @Override + public void shutdown() { + // do nothing + } + + public String tableToGcsKey(TableSpec tableSpec) { + return String.format("%s/%s" , tableSpec.toHivePartitionPostfix(), "backup_policy.json"); + } + + +} diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/bq/BigQueryServiceImpl.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/bq/BigQueryServiceImpl.java index 17db6f0..7e9e0e5 100644 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/bq/BigQueryServiceImpl.java +++ b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/bq/BigQueryServiceImpl.java @@ -19,13 +19,11 @@ import com.google.cloud.Timestamp; import com.google.cloud.Tuple; import com.google.cloud.bigquery.*; -import com.google.cloud.pso.bq_snapshot_manager.entities.Globals; import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.GCSSnapshotFormat; import javax.annotation.Nullable; import java.io.IOException; -import java.util.HashMap; import java.util.Map; public class BigQueryServiceImpl implements BigQueryService { diff --git a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/catalog/DataCatalogService.java b/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/catalog/DataCatalogService.java deleted file mode 100644 index e03e878..0000000 --- a/services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/catalog/DataCatalogService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.google.cloud.pso.bq_snapshot_manager.services.catalog; - -import com.google.cloud.datacatalog.v1.Entry; -import com.google.cloud.datacatalog.v1.LookupEntryRequest; -import com.google.cloud.datacatalog.v1.Tag; -import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupPolicy; -import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; - -import javax.annotation.Nullable; -import java.io.IOException; - -public interface DataCatalogService { - - Tag createOrUpdateBackupPolicyTag(TableSpec tableSpec, BackupPolicy backupPolicy, String backupPolicyTagTemplateId); - - @Nullable BackupPolicy getBackupPolicyTag(TableSpec tableSpec, String backupPolicyTagTemplateId) throws IOException, IllegalArgumentException; -} diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/entities/BackupPolicyTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/entities/BackupPolicyTest.java index fd9f606..50f322c 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/entities/BackupPolicyTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/entities/BackupPolicyTest.java @@ -311,13 +311,13 @@ public void testMissingValues() { public void testValidate_Required(){ BackupPolicy.BackupPolicyBuilder builder = new BackupPolicy.BackupPolicyBuilder(null,null,null,null,null); - List actual = BackupPolicy.validate(builder); - List expected = Arrays.asList( - DataCatalogBackupPolicyTagFields.backup_cron, - DataCatalogBackupPolicyTagFields.backup_method, - DataCatalogBackupPolicyTagFields.backup_time_travel_offset_days, - DataCatalogBackupPolicyTagFields.config_source, - DataCatalogBackupPolicyTagFields.backup_storage_project + List actual = BackupPolicy.validate(builder); + List expected = Arrays.asList( + BackupPolicyFields.backup_cron, + BackupPolicyFields.backup_method, + BackupPolicyFields.backup_time_travel_offset_days, + BackupPolicyFields.config_source, + BackupPolicyFields.backup_storage_project ); assertEquals(expected, actual); @@ -327,10 +327,10 @@ public void testValidate_Required(){ public void testValidate_BQSnapshot(){ BackupPolicy.BackupPolicyBuilder builder = new BackupPolicy.BackupPolicyBuilder("",BackupMethod.BIGQUERY_SNAPSHOT,TimeTravelOffsetDays.DAYS_0,BackupConfigSource.SYSTEM,""); - List actual = BackupPolicy.validate(builder); - List expected = Arrays.asList( - DataCatalogBackupPolicyTagFields.bq_snapshot_storage_dataset, - DataCatalogBackupPolicyTagFields.bq_snapshot_expiration_days + List actual = BackupPolicy.validate(builder); + List expected = Arrays.asList( + BackupPolicyFields.bq_snapshot_storage_dataset, + BackupPolicyFields.bq_snapshot_expiration_days ); assertEquals(expected, actual); @@ -341,10 +341,10 @@ public void testValidate_GCSSnapshot(){ BackupPolicy.BackupPolicyBuilder builder = new BackupPolicy.BackupPolicyBuilder("",BackupMethod.GCS_SNAPSHOT,TimeTravelOffsetDays.DAYS_0,BackupConfigSource.SYSTEM,""); - List actual = BackupPolicy.validate(builder); - List expected = Arrays.asList( - DataCatalogBackupPolicyTagFields.gcs_snapshot_format, - DataCatalogBackupPolicyTagFields.gcs_snapshot_storage_location + List actual = BackupPolicy.validate(builder); + List expected = Arrays.asList( + BackupPolicyFields.gcs_snapshot_format, + BackupPolicyFields.gcs_snapshot_storage_location ); assertEquals(expected, actual); @@ -356,11 +356,11 @@ public void testValidate_GCSSnapshotCSV(){ BackupPolicy.BackupPolicyBuilder builder = new BackupPolicy.BackupPolicyBuilder("",BackupMethod.GCS_SNAPSHOT,TimeTravelOffsetDays.DAYS_0,BackupConfigSource.SYSTEM,""); builder.setGcsExportFormat(GCSSnapshotFormat.CSV); - List actual = BackupPolicy.validate(builder); - List expected = Arrays.asList( - DataCatalogBackupPolicyTagFields.gcs_snapshot_storage_location, - DataCatalogBackupPolicyTagFields.gcs_csv_delimiter, - DataCatalogBackupPolicyTagFields.gcs_csv_export_header + List actual = BackupPolicy.validate(builder); + List expected = Arrays.asList( + BackupPolicyFields.gcs_snapshot_storage_location, + BackupPolicyFields.gcs_csv_delimiter, + BackupPolicyFields.gcs_csv_export_header ); assertEquals(expected, actual); @@ -372,10 +372,10 @@ public void testValidate_GCSSnapshotAvro(){ BackupPolicy.BackupPolicyBuilder builder = new BackupPolicy.BackupPolicyBuilder("",BackupMethod.GCS_SNAPSHOT,TimeTravelOffsetDays.DAYS_0,BackupConfigSource.SYSTEM,""); builder.setGcsExportFormat(GCSSnapshotFormat.AVRO_SNAPPY); - List actual = BackupPolicy.validate(builder); - List expected = Arrays.asList( - DataCatalogBackupPolicyTagFields.gcs_snapshot_storage_location, - DataCatalogBackupPolicyTagFields.gcs_avro_use_logical_types + List actual = BackupPolicy.validate(builder); + List expected = Arrays.asList( + BackupPolicyFields.gcs_snapshot_storage_location, + BackupPolicyFields.gcs_avro_use_logical_types ); assertEquals(expected, actual); diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/BigQueryScopeListerTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/BigQueryScopeListerTest.java index 970912d..07b763b 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/BigQueryScopeListerTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/BigQueryScopeListerTest.java @@ -20,7 +20,7 @@ public class BigQueryScopeListerTest { BigQueryScopeLister lister = new BigQueryScopeLister( new ResourceScannerTestImpl(), - new LoggingHelper("test", 1, "test-project"), + new LoggingHelper("test", 1, "test-project", "bq_backup_manager"), "R-testxxxxxxx" ); diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherTest.java index e14e43f..c0fd571 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f01_dispatcher/DispatcherTest.java @@ -54,7 +54,8 @@ public class DispatcherTest { "testProjectId", "testComputeRegionId", "testDataRegionId", - "testTaggerTopic" + "testTaggerTopic", + "bq_backup_manager" ); String runId = "1679574252412-R"; diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorTest.java index 1f98532..4dce9ce 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f02_configurator/ConfiguratorTest.java @@ -2,7 +2,6 @@ import com.google.cloud.Timestamp; import com.google.cloud.Tuple; -import com.google.cloud.datacatalog.v1.Tag; import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.GCSSnapshotFormat; import com.google.cloud.pso.bq_snapshot_manager.entities.NonRetryableApplicationException; import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; @@ -14,13 +13,12 @@ import com.google.cloud.pso.bq_snapshot_manager.services.PersistentSetTestImpl; import com.google.cloud.pso.bq_snapshot_manager.services.PubSubServiceTestImpl; import com.google.cloud.pso.bq_snapshot_manager.services.bq.BigQueryService; -import com.google.cloud.pso.bq_snapshot_manager.services.catalog.DataCatalogService; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyService; import com.google.cloud.pso.bq_snapshot_manager.services.pubsub.PubSubPublishResults; import org.junit.Test; import javax.annotation.Nullable; import java.io.IOException; -import java.sql.Time; import java.time.LocalDateTime; import java.util.AbstractMap; import java.util.Map; @@ -35,7 +33,8 @@ public class ConfiguratorTest { LoggingHelper testLogger = new LoggingHelper( ConfiguratorTest.class.getSimpleName(), 2, - "testProject" + "testProject", + "bq_backup_manager" ); String jsonPolicyStr = "{\n" + @@ -334,7 +333,8 @@ private ConfiguratorResponse executeConfigurator( "test-project", "test-bqSnapshoterTopic", "test-gcsSnapshoterTopic", - "test-templateId" + "test-templateId", + "bq_backup_manager" ); Configurator configurator = new Configurator( @@ -355,18 +355,22 @@ public Long getTableCreationTime(TableSpec table) { return Utils.timestampToUnixTimeMillis(tableCreationTS); } }, - new DataCatalogService() { + new BackupPolicyService() { @Override - public Tag createOrUpdateBackupPolicyTag(TableSpec tableSpec, BackupPolicy backupPolicy, String backupPolicyTagTemplateId) { + public void createOrUpdateBackupPolicyForTable(TableSpec tableSpec, BackupPolicy backupPolicy) { - return null; } @Override - public @Nullable BackupPolicy getBackupPolicyTag(TableSpec tableSpec, String backupPolicyTagTemplateId) throws IOException, IllegalArgumentException { + public @Nullable BackupPolicy getBackupPolicyForTable(TableSpec tableSpec) throws IOException, IllegalArgumentException { return testBackupPolicy; } + + @Override + public void shutdown() { + + } }, new PubSubServiceTestImpl(), new PersistentSetTestImpl(), diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoterTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoterTest.java index 7419a20..d5b2141 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoterTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/BigQuerySnapshoterTest.java @@ -41,7 +41,7 @@ public void testGetSnapshotTableSpec() { public void testExecute() throws NonRetryableApplicationException, IOException, InterruptedException { BigQuerySnapshoter snapshoter = new BigQuerySnapshoter( - new SnapshoterConfig("host-project", "data-region"), + new SnapshoterConfig("host-project", "data-region", "bq_backup_manager"), new BigQueryService() { @Override public void createSnapshot(String jobId, TableSpec sourceTable, TableSpec destinationId, Timestamp snapshotExpirationTs, String trackingId) throws InterruptedException { diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoterTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoterTest.java index b58dbaa..4260026 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoterTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/functions/f03_snapshoter/GCSSnapshoterTest.java @@ -42,7 +42,7 @@ public void testPrepareGcsUriForMultiFileExport() { public void testExecute() throws NonRetryableApplicationException, IOException, InterruptedException { GCSSnapshoter gcsSnapshoter = new GCSSnapshoter( - new SnapshoterConfig("host-project", "data-region"), + new SnapshoterConfig("host-project", "data-region", "bq_backup_manager"), new BigQueryService() { @Override public void createSnapshot(String jobId, TableSpec sourceTable, TableSpec destinationId, Timestamp snapshotExpirationTs, String trackingId) throws InterruptedException { diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/ControllerExceptionHelperTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/ControllerExceptionHelperTest.java index 12d16e9..ecaffe2 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/ControllerExceptionHelperTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/ControllerExceptionHelperTest.java @@ -33,7 +33,7 @@ public class ControllerExceptionHelperTest { @Test public void testRetryableApiException() { - LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test"); + LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test", "bq_backup_manager"); try { @@ -64,7 +64,7 @@ public Object getTransportCode() { @Test public void testNonRetryableApiException() { - LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test"); + LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test","bq_backup_manager"); try { @@ -95,7 +95,7 @@ public Object getTransportCode() { @Test public void testRetryableIOException() { - LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test"); + LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test", "bq_backup_manager"); try { @@ -115,7 +115,7 @@ public void testRetryableIOException() { @Test public void testRetryableRuntimeStatusResourceExhaustedException() { - LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test"); + LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test", "bq_backup_manager"); try { @@ -135,7 +135,7 @@ public void testRetryableRuntimeStatusResourceExhaustedException() { @Test public void testRetryableResourceExhaustedException() { - LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test"); + LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test", "bq_backup_manager"); try { @@ -169,7 +169,7 @@ public Object getTransportCode() { @Test public void testNestedRetryableException() { - LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test"); + LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test", "bq_backup_manager"); try { Throwable cause = new java.net.SocketException ("test socket exception"); @@ -196,7 +196,7 @@ public void testNestedRetryableException() { @Test public void testNonRetryableException() { - LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test"); + LoggingHelper logger = new LoggingHelper(ControllerExceptionHelperTest.class.getSimpleName(), 0, "test", "bq_backup_manager"); try { diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelperTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelperTest.java index 803848d..ecf3160 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelperTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/TrackingHelperTest.java @@ -21,7 +21,7 @@ public void parseAsTimestamp(){ public void parseTrackingIdFromJobId(){ String trackingId = TrackingHelper.generateTrackingId(TrackingHelper.MIN_RUN_ID); String parsedTrackingId = TrackingHelper.parseTrackingIdFromBQExportJobId( - TrackingHelper.generateBQExportJobId(trackingId) + TrackingHelper.generateBQExportJobId(trackingId, "bq_backup_manager") ); assertEquals(trackingId, parsedTrackingId); diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/UtilsTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/UtilsTest.java index 6431ce3..b3d794f 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/UtilsTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/helpers/UtilsTest.java @@ -59,7 +59,7 @@ public void testGetTableSpecWithTimeTravel(){ refPoint ); - Long expectedMs7Days = (1665665921000L - (7 * 86400000)) + 60000; + Long expectedMs7Days = (1665665921000L - (7 * 86400000)) + 60* 60000; assertEquals(TableSpec.fromSqlString("p.d.t@"+expectedMs7Days.toString()), actualWith7.x()); assertEquals(expectedMs7Days, actualWith7.y()); diff --git a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/services/DataCatalogServiceImplTest.java b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/services/BackupPolicyServiceDataCatalogImplTest.java similarity index 75% rename from services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/services/DataCatalogServiceImplTest.java rename to services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/services/BackupPolicyServiceDataCatalogImplTest.java index 43f32b6..57d2c9e 100644 --- a/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/services/DataCatalogServiceImplTest.java +++ b/services/library/src/test/java/com/google/cloud/pso/bq_snapshot_manager/services/BackupPolicyServiceDataCatalogImplTest.java @@ -1,25 +1,15 @@ package com.google.cloud.pso.bq_snapshot_manager.services; -import com.google.cloud.Timestamp; import com.google.cloud.datacatalog.v1.TagField; -import com.google.cloud.pso.bq_snapshot_manager.entities.*; -import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupConfigSource; -import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupMethod; -import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.BackupPolicy; -import com.google.cloud.pso.bq_snapshot_manager.entities.backup_policy.TimeTravelOffsetDays; -import com.google.cloud.pso.bq_snapshot_manager.helpers.Utils; -import com.google.cloud.pso.bq_snapshot_manager.services.catalog.DataCatalogServiceImpl; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyServiceDataCatalogImpl; import org.junit.Test; -import org.springframework.test.context.TestExecutionListeners; -import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; -public class DataCatalogServiceImplTest { +public class BackupPolicyServiceDataCatalogImplTest { @Test public void testConvertTagFieldMapToStrMap() { @@ -83,7 +73,7 @@ public void testConvertTagFieldMapToStrMap() { expected.put("bq_snapshot_expiration_days","0.0"); expected.put("gcs_snapshot_storage_location","test-bucket"); - Map actual = DataCatalogServiceImpl.convertTagFieldMapToStrMap(tagMap); + Map actual = BackupPolicyServiceDataCatalogImpl.convertTagFieldMapToStrMap(tagMap); assertEquals(expected, actual); } diff --git a/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/BigQuerySnapshoterController.java b/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/BigQuerySnapshoterController.java index f47c5a5..86f91da 100644 --- a/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/BigQuerySnapshoterController.java +++ b/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/BigQuerySnapshoterController.java @@ -56,7 +56,8 @@ public BigQuerySnapshoterController() { logger = new LoggingHelper( BigQuerySnapshoterController.class.getSimpleName(), functionNumber, - environment.getProjectId() + environment.getProjectId(), + environment.getApplicationName() ); } diff --git a/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/Environment.java b/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/Environment.java index b1efd8e..87916d5 100644 --- a/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/Environment.java +++ b/services/snapshoter-bq-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_bq/Environment.java @@ -26,7 +26,8 @@ public SnapshoterConfig toConfig (){ return new SnapshoterConfig( getProjectId(), - getOutputTopic() + getOutputTopic(), + getApplicationName() ); } @@ -40,4 +41,7 @@ public String getProjectId(){ public String getGcsFlagsBucket(){ return Utils.getConfigFromEnv("GCS_FLAGS_BUCKET", true); } + public String getApplicationName(){ + return Utils.getConfigFromEnv("APPLICATION_NAME", true); + } } diff --git a/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/Environment.java b/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/Environment.java index 827211a..47be1f5 100644 --- a/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/Environment.java +++ b/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/Environment.java @@ -26,7 +26,8 @@ public SnapshoterConfig toConfig (){ return new SnapshoterConfig( getProjectId(), - getOutputTopic() + getOutputTopic(), + getApplicationName() ); } @@ -40,4 +41,8 @@ public String getProjectId(){ public String getGcsFlagsBucket(){ return Utils.getConfigFromEnv("GCS_FLAGS_BUCKET", true); } + public String getApplicationName(){ + return Utils.getConfigFromEnv("APPLICATION_NAME", true); + } + } diff --git a/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/GCSSnapshoterController.java b/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/GCSSnapshoterController.java index 3137185..2877c6d 100644 --- a/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/GCSSnapshoterController.java +++ b/services/snapshoter-gcs-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/snapshoter_gcs/GCSSnapshoterController.java @@ -58,7 +58,8 @@ public GCSSnapshoterController() { logger = new LoggingHelper( GCSSnapshoterController.class.getSimpleName(), functionNumber, - environment.getProjectId() + environment.getProjectId(), + environment.getApplicationName() ); } diff --git a/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/Environment.java b/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/Environment.java index f260cde..6aa0b3a 100644 --- a/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/Environment.java +++ b/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/Environment.java @@ -23,7 +23,8 @@ public class Environment { public TaggerConfig toConfig (){ return new TaggerConfig( getProjectId(), - getTagTemplateId() + getTagTemplateId(), + getApplicationName() ); } @@ -38,5 +39,11 @@ public String getTagTemplateId(){ public String getGcsFlagsBucket(){ return Utils.getConfigFromEnv("GCS_FLAGS_BUCKET", true); } + public String getApplicationName(){ + return Utils.getConfigFromEnv("APPLICATION_NAME", true); + } + public String getGcsBackupPoliciesBucket(){ + return Utils.getConfigFromEnv("GCS_BACKUP_POLICIES_BUCKET", true); + } } diff --git a/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/TaggerController.java b/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/TaggerController.java index 214c44b..69a3b1e 100644 --- a/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/TaggerController.java +++ b/services/tagger-app/src/main/java/com/google/cloud/pso/bq_snapshot_manager/tagger/TaggerController.java @@ -18,21 +18,19 @@ import com.google.cloud.Tuple; import com.google.cloud.pso.bq_snapshot_manager.entities.NonRetryableApplicationException; import com.google.cloud.pso.bq_snapshot_manager.entities.PubSubEvent; -import com.google.cloud.pso.bq_snapshot_manager.entities.TableSpec; -import com.google.cloud.pso.bq_snapshot_manager.functions.f03_snapshoter.BigQuerySnapshoter; -import com.google.cloud.pso.bq_snapshot_manager.functions.f03_snapshoter.GCSSnapshoter; import com.google.cloud.pso.bq_snapshot_manager.functions.f04_tagger.Tagger; import com.google.cloud.pso.bq_snapshot_manager.functions.f04_tagger.TaggerResponse; import com.google.cloud.pso.bq_snapshot_manager.functions.f04_tagger.TaggerRequest; import com.google.cloud.pso.bq_snapshot_manager.helpers.ControllerExceptionHelper; import com.google.cloud.pso.bq_snapshot_manager.helpers.LoggingHelper; import com.google.cloud.pso.bq_snapshot_manager.helpers.TrackingHelper; -import com.google.cloud.pso.bq_snapshot_manager.services.catalog.DataCatalogServiceImpl; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyService; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyServiceFireStoreImpl; +import com.google.cloud.pso.bq_snapshot_manager.services.backup_policy.BackupPolicyServiceGCSImpl; import com.google.cloud.pso.bq_snapshot_manager.services.map.GcsPersistentMapImpl; import com.google.cloud.pso.bq_snapshot_manager.services.map.PersistentMap; import com.google.cloud.pso.bq_snapshot_manager.services.set.GCSPersistentSetImpl; import com.google.gson.Gson; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import org.springframework.boot.SpringApplication; @@ -60,7 +58,8 @@ public TaggerController() { logger = new LoggingHelper( TaggerController.class.getSimpleName(), functionNumber, - environment.getProjectId() + environment.getProjectId(), + environment.getApplicationName() ); } @@ -68,7 +67,7 @@ public TaggerController() { public ResponseEntity receiveMessage(@RequestBody PubSubEvent requestBody) { String trackingId = TrackingHelper.MIN_RUN_ID; - DataCatalogServiceImpl dataCatalogService = null; + BackupPolicyService backupPolicyService = null; // These values will be updated based on the execution flow and logged at the end ResponseEntity responseEntity; @@ -128,13 +127,13 @@ public ResponseEntity receiveMessage(@RequestBody PubSubEvent requestBody) { logger.logInfoWithTracker(taggerRequest.isDryRun(), trackingId, taggerRequest.getTargetTable(), String.format("Parsed Request: %s", taggerRequest.toString())); - dataCatalogService = new DataCatalogServiceImpl(); + backupPolicyService = new BackupPolicyServiceGCSImpl(environment.getGcsBackupPoliciesBucket()); Tagger tagger = new Tagger( - new LoggingHelper(Tagger.class.getSimpleName(), functionNumber, environment.getProjectId()), environment.toConfig(), - dataCatalogService, + backupPolicyService, new GCSPersistentSetImpl(environment.getGcsFlagsBucket()), - "tagger-flags" + "tagger-flags", + functionNumber ); taggerResponse = tagger.execute( @@ -157,8 +156,8 @@ public ResponseEntity receiveMessage(@RequestBody PubSubEvent requestBody) { error = e; }finally { - if(dataCatalogService != null){ - dataCatalogService.shutdown(); + if(backupPolicyService != null){ + backupPolicyService.shutdown(); } } diff --git a/terraform/main.tf b/terraform/main.tf index c074146..90b4de1 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -70,6 +70,10 @@ locals { name = "GCS_FLAGS_BUCKET", value = module.gcs.create_gcs_flags_bucket_name }, + { + name = "GCS_BACKUP_POLICIES_BUCKET", + value = module.gcs.create_gcs_backup_policies_bucket_name + }, { name = "APPLICATION_NAME", value = var.application_name @@ -111,7 +115,6 @@ module "gcs" { source = "./modules/gcs" gcs_flags_bucket_name = "${var.project}-${var.gcs_flags_bucket_name}" project = var.project - region = var.compute_region # because it's used by the cloud run services # both dispatchers should be admins. Add the inspection-dispatcher-sa only if it's being deployed gcs_flags_bucket_admins = [ @@ -122,6 +125,13 @@ module "gcs" { "serviceAccount:${module.iam.sa_tagger_email}", ] common_labels = local.common_labels + gcs_backup_policies_bucket_admins = [ + "serviceAccount:${module.iam.sa_configurator_email}", + "serviceAccount:${module.iam.sa_tagger_email}", + ] + gcs_backup_policies_bucket_name = "${var.project}-${var.gcs_backup_policies_bucket_name}" + compute_region = var.compute_region + data_region = var.data_region } module "bigquery" { @@ -131,6 +141,7 @@ module "bigquery" { dataset = var.bigquery_dataset_name logging_sink_sa = module.cloud_logging.service_account common_labels = local.common_labels + gcs_backup_policies_bucket_name = module.gcs.create_gcs_backup_policies_bucket_name } module "cloud_logging" { diff --git a/terraform/modules/bigquery/main.tf b/terraform/modules/bigquery/main.tf index e508ba8..037c31a 100644 --- a/terraform/modules/bigquery/main.tf +++ b/terraform/modules/bigquery/main.tf @@ -8,7 +8,6 @@ resource "google_bigquery_dataset" "results_dataset" { project = var.project location = var.region dataset_id = var.dataset - description = "To store DLP results from BQ Security Classifier app" labels = var.common_labels } @@ -246,6 +245,29 @@ resource "google_bigquery_table" "view_run_duration" { } +########## External tables ##################################### + +resource "google_bigquery_table" "external_gcs_backup_policies" { + dataset_id = google_bigquery_dataset.results_dataset.dataset_id + table_id = "ext_backup_policies" + + external_data_configuration { + source_format = "NEWLINE_DELIMITED_JSON" + hive_partitioning_options { + mode = "CUSTOM" # Custom means you must encode the partition key schema within the source_uri_prefix + source_uri_prefix = "gs://${var.gcs_backup_policies_bucket_name}/{project:STRING}/{dataset:STRING}/{table:STRING}" + + } + source_uris = [ + "gs://${var.gcs_backup_policies_bucket_name}/*.json", + ] + autodetect = false # Let BigQuery try to autodetect the schema and format of the table. + schema = file("modules/bigquery/schema/ext_backup_policies.json") + } + + deletion_protection = false +} + diff --git a/terraform/modules/bigquery/schema/ext_backup_policies.json b/terraform/modules/bigquery/schema/ext_backup_policies.json new file mode 100644 index 0000000..3fadd01 --- /dev/null +++ b/terraform/modules/bigquery/schema/ext_backup_policies.json @@ -0,0 +1,88 @@ +[ + { + "mode": "NULLABLE", + "name": "config_source", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "backup_cron", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "backup_method", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "backup_time_travel_offset_days", + "type": "INT64" + }, + { + "mode": "NULLABLE", + "name": "backup_storage_project", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "backup_operation_project", + "type": "STRING" + }, + + + + + + { + "mode": "NULLABLE", + "name": "bq_snapshot_storage_dataset", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "bq_snapshot_expiration_days", + "type": "FLOAT" + }, + { + "mode": "NULLABLE", + "name": "gcs_snapshot_storage_location", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "gcs_snapshot_format", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "gcs_csv_delimiter", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "gcs_csv_export_header", + "type": "BOOLEAN" + }, + { + "mode": "NULLABLE", + "name": "gcs_avro_use_logical_types", + "type": "BOOLEAN" + }, + { + "mode": "NULLABLE", + "name": "last_backup_at", + "type": "TIMESTAMP" + }, + { + "mode": "NULLABLE", + "name": "last_bq_snapshot_storage_uri", + "type": "STRING" + }, + { + "mode": "NULLABLE", + "name": "last_gcs_snapshot_storage_uri", + "type": "STRING" + } +] + diff --git a/terraform/modules/bigquery/variables.tf b/terraform/modules/bigquery/variables.tf index dd774cb..57432a0 100644 --- a/terraform/modules/bigquery/variables.tf +++ b/terraform/modules/bigquery/variables.tf @@ -18,6 +18,10 @@ variable "common_labels" { type = map(string) } +variable "gcs_backup_policies_bucket_name" { + type = string +} + diff --git a/terraform/modules/bigquery/views/v_audit_log_by_table.tpl b/terraform/modules/bigquery/views/v_audit_log_by_table.tpl index 4c039ef..5b738cd 100644 --- a/terraform/modules/bigquery/views/v_audit_log_by_table.tpl +++ b/terraform/modules/bigquery/views/v_audit_log_by_table.tpl @@ -21,7 +21,7 @@ CAST(JSON_VALUE(jsonPayload.unified_input_json, '$.isForceRun') AS BOOL) AS is_f CAST(JSON_VALUE(jsonPayload.unified_output_json, '$.isBackupCronTime') AS BOOL) AS is_backup_cron_time, CAST(JSON_VALUE(jsonPayload.unified_output_json, '$.isTableCreatedBeforeTimeTravel') AS BOOL) AS is_table_created_before_time_travel, CAST(JSON_VALUE(jsonPayload.unified_output_json, '$.isBackupTime') AS BOOL) AS is_backup_time, -JSON_VALUE(jsonPayload.unified_output_json, '$.backupPolicy.method') AS backup_method, +JSON_VALUE(jsonPayload.unified_output_json, '$.backupPolicy.backup_method') AS backup_method, CAST(JSON_VALUE(jsonPayload.unified_input_json, '$.isDryRun') AS BOOL) AS is_dry_run, timestamp AS configurator_log_ts FROM `${project}.${dataset}.${logging_table}` diff --git a/terraform/modules/bigquery/views/v_service_calls.tpl b/terraform/modules/bigquery/views/v_service_calls.tpl index 832aaee..55f3515 100644 --- a/terraform/modules/bigquery/views/v_service_calls.tpl +++ b/terraform/modules/bigquery/views/v_service_calls.tpl @@ -12,5 +12,5 @@ SUM(CASE WHEN step = 'START' AND function_number = 4 THEN 1 ELSE 0 END) AS tagg SUM(CASE WHEN step = 'END' AND function_number = 4 THEN 1 ELSE 0 END) AS tagger_ends FROM `${project}.${dataset}.${logging_view_steps}` -WHERE function_number > 1 +WHERE function_number <> 1 GROUP BY 1,2,3 \ No newline at end of file diff --git a/terraform/modules/gcs/main.tf b/terraform/modules/gcs/main.tf index a0e558c..4baf248 100644 --- a/terraform/modules/gcs/main.tf +++ b/terraform/modules/gcs/main.tf @@ -4,7 +4,7 @@ resource "google_storage_bucket" "gcs_flags_bucket" { project = var.project name = var.gcs_flags_bucket_name # This bucket is used by the services so let's create in the same compute region - location = var.region + location = var.compute_region # force_destroy = true @@ -28,3 +28,25 @@ resource "google_storage_bucket_iam_binding" "gcs_flags_bucket_iam_bindings" { role = "roles/storage.objectAdmin" members = var.gcs_flags_bucket_admins } + + +// Backup Polices + +resource "google_storage_bucket" "gcs_backup_policies_bucket" { + project = var.project + name = var.gcs_backup_policies_bucket_name + # This bucket must be created in the same region that BigQuery dataset is created + location = var.data_region + + force_destroy = false + + uniform_bucket_level_access = true + + labels = var.common_labels +} + +resource "google_storage_bucket_iam_binding" "gcs_backup_policies_iam_bindings" { + bucket = google_storage_bucket.gcs_backup_policies_bucket.name + role = "roles/storage.objectAdmin" + members = var.gcs_backup_policies_bucket_admins +} \ No newline at end of file diff --git a/terraform/modules/gcs/output.tf b/terraform/modules/gcs/output.tf index 66cef1d..41fa88d 100644 --- a/terraform/modules/gcs/output.tf +++ b/terraform/modules/gcs/output.tf @@ -1,3 +1,7 @@ output "create_gcs_flags_bucket_name" { value = google_storage_bucket.gcs_flags_bucket.name +} + +output "create_gcs_backup_policies_bucket_name" { + value = google_storage_bucket.gcs_backup_policies_bucket.name } \ No newline at end of file diff --git a/terraform/modules/gcs/variables.tf b/terraform/modules/gcs/variables.tf index 295b224..7fd67c8 100644 --- a/terraform/modules/gcs/variables.tf +++ b/terraform/modules/gcs/variables.tf @@ -1,6 +1,8 @@ variable "project" {type = string} -variable "region" {type = string} +variable "compute_region" {type = string} + +variable "data_region" {type = string} variable "gcs_flags_bucket_name" {type = string} @@ -8,6 +10,12 @@ variable "gcs_flags_bucket_admins" { type = list(string) } +variable "gcs_backup_policies_bucket_name" {type = string} + +variable "gcs_backup_policies_bucket_admins" { + type = list(string) +} + variable "common_labels" { type = map(string) } \ No newline at end of file diff --git a/terraform/modules/iam/main.tf b/terraform/modules/iam/main.tf index 884e749..fef0131 100644 --- a/terraform/modules/iam/main.tf +++ b/terraform/modules/iam/main.tf @@ -83,6 +83,14 @@ resource "google_service_account_iam_member" "sa_dispatcher_account_user_sa_disp #### Configurator SA Permissions ### +// read backup policies when using datastore as backend +resource "google_project_iam_member" "sa_configurator_datastore_viewer" { +project = var.project +role = "roles/datastore.viewer" +member = "serviceAccount:${google_service_account.sa_configurator.email}" +} + +// read backup policies when using data catalog as backend resource "google_project_iam_member" "sa_configurator_datacatalog_viewer" { project = var.project role = "roles/datacatalog.viewer" @@ -116,6 +124,14 @@ resource "google_service_account_iam_member" "sa_snapshoter_gcs_account_user_sa_ } #### Tagger SA Permissions ### + +// read / write for backup policies when using datastore as backend +resource "google_project_iam_member" "sa_tagger_datastore_user" { +project = var.project +role = "roles/datastore.user" +member = "serviceAccount:${google_service_account.sa_tagger.email}" +} + resource "google_project_iam_member" "sa_tagger_datacatalog_viewer" { project = var.project role = "roles/datacatalog.viewer" diff --git a/terraform/variables.tf b/terraform/variables.tf index 339d28d..1724554 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -171,7 +171,12 @@ variable "tagger_pubsub_sub" { variable "gcs_flags_bucket_name" { type = string - default = "bq-snapshot-mgr-flags" + default = "bq-backup-manager-flags" +} + +variable "gcs_backup_policies_bucket_name" { + type = string + default = "bq-backup-manager-policies" } # Images