From e7ba735644cd0b37a3339f2beb33451d80c751f3 Mon Sep 17 00:00:00 2001 From: The Magician Date: Thu, 9 May 2024 06:33:47 -0700 Subject: [PATCH] Add cloud_sql_target field in google_data_loss_prevention_discovery_config (#10625) (#18063) [upstream:87fd42db32f8f42ef9335284cf3f63c1abb578fe] Signed-off-by: Modular Magician --- ...e_data_loss_prevention_discovery_config.go | 633 ++++++++++++++++++ ...vention_discovery_config_generated_test.go | 109 +++ ...a_loss_prevention_discovery_config_test.go | 156 ++++- ..._prevention_discovery_config.html.markdown | 193 ++++++ 4 files changed, 1090 insertions(+), 1 deletion(-) diff --git a/google/services/datalossprevention/resource_data_loss_prevention_discovery_config.go b/google/services/datalossprevention/resource_data_loss_prevention_discovery_config.go index 6420b6069c3..f5b525bdbd7 100644 --- a/google/services/datalossprevention/resource_data_loss_prevention_discovery_config.go +++ b/google/services/datalossprevention/resource_data_loss_prevention_discovery_config.go @@ -445,6 +445,162 @@ func ResourceDataLossPreventionDiscoveryConfig() *schema.Resource { }, }, }, + "cloud_sql_target": { + Type: schema.TypeList, + Optional: true, + Description: `Cloud SQL target for Discovery. The first target to match a table will be the one applied.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "filter": { + Type: schema.TypeList, + Required: true, + Description: `Required. The tables the discovery cadence applies to. The first target with a matching filter will be the one to apply to a table.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "collection": { + Type: schema.TypeList, + Optional: true, + Description: `A specific set of database resources for this filter to apply to.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "include_regexes": { + Type: schema.TypeList, + Optional: true, + Description: `A collection of regular expressions to match a database resource against.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "patterns": { + Type: schema.TypeList, + Optional: true, + Description: `A group of regular expression patterns to match against one or more database resources. Maximum of 100 entries. The sum of all regular expressions' length can't exceed 10 KiB.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "database_regex": { + Type: schema.TypeString, + Optional: true, + Description: `Regex to test the database name against. If empty, all databases match.`, + }, + "database_resource_name_regex": { + Type: schema.TypeString, + Optional: true, + Description: `Regex to test the database resource's name against. An example of a database resource name is a table's name. Other database resource names like view names could be included in the future. If empty, all database resources match.'`, + }, + "instance_regex": { + Type: schema.TypeString, + Optional: true, + Description: `Regex to test the instance name against. If empty, all instances match.`, + }, + "project_id_regex": { + Type: schema.TypeString, + Optional: true, + Description: `For organizations, if unset, will match all projects. Has no effect for data profile configurations created within a project.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "others": { + Type: schema.TypeList, + Optional: true, + Description: `Catch-all. This should always be the last target in the list because anything above it will apply first. Should only appear once in a configuration. If none is specified, a default one will be added automatically.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{}, + }, + }, + }, + }, + }, + "conditions": { + Type: schema.TypeList, + Optional: true, + Description: `In addition to matching the filter, these conditions must be true before a profile is generated.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "database_engines": { + Type: schema.TypeList, + Optional: true, + Description: `Database engines that should be profiled. Optional. Defaults to ALL_SUPPORTED_DATABASE_ENGINES if unspecified. Possible values: ["ALL_SUPPORTED_DATABASE_ENGINES", "MYSQL", "POSTGRES"]`, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: verify.ValidateEnum([]string{"ALL_SUPPORTED_DATABASE_ENGINES", "MYSQL", "POSTGRES"}), + }, + }, + "types": { + Type: schema.TypeList, + Optional: true, + Description: `Data profiles will only be generated for the database resource types specified in this field. If not specified, defaults to [DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES]. Possible values: ["DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES", "DATABASE_RESOURCE_TYPE_TABLE"]`, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: verify.ValidateEnum([]string{"DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES", "DATABASE_RESOURCE_TYPE_TABLE"}), + }, + }, + }, + }, + }, + "disabled": { + Type: schema.TypeList, + Optional: true, + Description: `Disable profiling for database resources that match this filter.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{}, + }, + }, + "generation_cadence": { + Type: schema.TypeList, + Optional: true, + Description: `How often and when to update profiles. New tables that match both the filter and conditions are scanned as quickly as possible depending on system capacity.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "refresh_frequency": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"UPDATE_FREQUENCY_NEVER", "UPDATE_FREQUENCY_DAILY", "UPDATE_FREQUENCY_MONTHLY", ""}), + Description: `Data changes (non-schema changes) in Cloud SQL tables can't trigger reprofiling. If you set this field, profiles are refreshed at this frequency regardless of whether the underlying tables have changes. Defaults to never. Possible values: ["UPDATE_FREQUENCY_NEVER", "UPDATE_FREQUENCY_DAILY", "UPDATE_FREQUENCY_MONTHLY"]`, + }, + "schema_modified_cadence": { + Type: schema.TypeList, + Optional: true, + Description: `Governs when to update data profiles when a schema is modified`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "frequency": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"UPDATE_FREQUENCY_NEVER", "UPDATE_FREQUENCY_DAILY", "UPDATE_FREQUENCY_MONTHLY", ""}), + Description: `Frequency to regenerate data profiles when the schema is modified. Defaults to monthly. Possible values: ["UPDATE_FREQUENCY_NEVER", "UPDATE_FREQUENCY_DAILY", "UPDATE_FREQUENCY_MONTHLY"]`, + }, + "types": { + Type: schema.TypeList, + Optional: true, + Description: `The types of schema modifications to consider. Defaults to NEW_COLUMNS. Possible values: ["NEW_COLUMNS", "REMOVED_COLUMNS"]`, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: verify.ValidateEnum([]string{"NEW_COLUMNS", "REMOVED_COLUMNS"}), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -1108,6 +1264,7 @@ func flattenDataLossPreventionDiscoveryConfigTargets(v interface{}, d *schema.Re } transformed = append(transformed, map[string]interface{}{ "big_query_target": flattenDataLossPreventionDiscoveryConfigTargetsBigQueryTarget(original["bigQueryTarget"], d, config), + "cloud_sql_target": flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTarget(original["cloudSqlTarget"], d, config), }) } return transformed @@ -1361,6 +1518,184 @@ func flattenDataLossPreventionDiscoveryConfigTargetsBigQueryTargetDisabled(v int return []interface{}{transformed} } +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTarget(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["filter"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilter(original["filter"], d, config) + transformed["conditions"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditions(original["conditions"], d, config) + transformed["generation_cadence"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadence(original["generationCadence"], d, config) + transformed["disabled"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetDisabled(original["disabled"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilter(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["collection"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollection(original["collection"], d, config) + transformed["others"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterOthers(original["others"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollection(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["include_regexes"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexes(original["includeRegexes"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexes(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["patterns"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatterns(original["patterns"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatterns(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "project_id_regex": flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsProjectIdRegex(original["projectIdRegex"], d, config), + "instance_regex": flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsInstanceRegex(original["instanceRegex"], d, config), + "database_regex": flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseRegex(original["databaseRegex"], d, config), + "database_resource_name_regex": flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseResourceNameRegex(original["databaseResourceNameRegex"], d, config), + }) + } + return transformed +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsProjectIdRegex(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsInstanceRegex(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseRegex(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseResourceNameRegex(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterOthers(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + transformed := make(map[string]interface{}) + return []interface{}{transformed} +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditions(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["database_engines"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsDatabaseEngines(original["databaseEngines"], d, config) + transformed["types"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsTypes(original["types"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsDatabaseEngines(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsTypes(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadence(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["schema_modified_cadence"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadence(original["schemaModifiedCadence"], d, config) + transformed["refresh_frequency"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceRefreshFrequency(original["refreshFrequency"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadence(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["types"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceTypes(original["types"], d, config) + transformed["frequency"] = + flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceFrequency(original["frequency"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceTypes(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceFrequency(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceRefreshFrequency(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetDisabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + transformed := make(map[string]interface{}) + return []interface{}{transformed} +} + func flattenDataLossPreventionDiscoveryConfigErrors(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return v @@ -1762,6 +2097,13 @@ func expandDataLossPreventionDiscoveryConfigTargets(v interface{}, d tpgresource transformed["bigQueryTarget"] = transformedBigQueryTarget } + transformedCloudSqlTarget, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTarget(original["cloud_sql_target"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCloudSqlTarget); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["cloudSqlTarget"] = transformedCloudSqlTarget + } + req = append(req, transformed) } return req, nil @@ -2148,6 +2490,297 @@ func expandDataLossPreventionDiscoveryConfigTargetsBigQueryTargetDisabled(v inte return transformed, nil } +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTarget(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedFilter, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilter(original["filter"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFilter); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["filter"] = transformedFilter + } + + transformedConditions, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditions(original["conditions"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedConditions); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["conditions"] = transformedConditions + } + + transformedGenerationCadence, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadence(original["generation_cadence"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGenerationCadence); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["generationCadence"] = transformedGenerationCadence + } + + transformedDisabled, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetDisabled(original["disabled"], d, config) + if err != nil { + return nil, err + } else { + transformed["disabled"] = transformedDisabled + } + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilter(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedCollection, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollection(original["collection"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCollection); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["collection"] = transformedCollection + } + + transformedOthers, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterOthers(original["others"], d, config) + if err != nil { + return nil, err + } else { + transformed["others"] = transformedOthers + } + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollection(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedIncludeRegexes, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexes(original["include_regexes"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIncludeRegexes); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["includeRegexes"] = transformedIncludeRegexes + } + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexes(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedPatterns, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatterns(original["patterns"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPatterns); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["patterns"] = transformedPatterns + } + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatterns(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedProjectIdRegex, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsProjectIdRegex(original["project_id_regex"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProjectIdRegex); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["projectIdRegex"] = transformedProjectIdRegex + } + + transformedInstanceRegex, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsInstanceRegex(original["instance_regex"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInstanceRegex); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["instanceRegex"] = transformedInstanceRegex + } + + transformedDatabaseRegex, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseRegex(original["database_regex"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDatabaseRegex); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["databaseRegex"] = transformedDatabaseRegex + } + + transformedDatabaseResourceNameRegex, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseResourceNameRegex(original["database_resource_name_regex"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDatabaseResourceNameRegex); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["databaseResourceNameRegex"] = transformedDatabaseResourceNameRegex + } + + req = append(req, transformed) + } + return req, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsProjectIdRegex(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsInstanceRegex(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseRegex(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterCollectionIncludeRegexesPatternsDatabaseResourceNameRegex(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetFilterOthers(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 { + return nil, nil + } + + if l[0] == nil { + transformed := make(map[string]interface{}) + return transformed, nil + } + transformed := make(map[string]interface{}) + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditions(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDatabaseEngines, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsDatabaseEngines(original["database_engines"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDatabaseEngines); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["databaseEngines"] = transformedDatabaseEngines + } + + transformedTypes, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsTypes(original["types"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTypes); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["types"] = transformedTypes + } + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsDatabaseEngines(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetConditionsTypes(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadence(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedSchemaModifiedCadence, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadence(original["schema_modified_cadence"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSchemaModifiedCadence); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["schemaModifiedCadence"] = transformedSchemaModifiedCadence + } + + transformedRefreshFrequency, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceRefreshFrequency(original["refresh_frequency"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRefreshFrequency); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["refreshFrequency"] = transformedRefreshFrequency + } + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadence(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTypes, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceTypes(original["types"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTypes); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["types"] = transformedTypes + } + + transformedFrequency, err := expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceFrequency(original["frequency"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFrequency); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["frequency"] = transformedFrequency + } + + return transformed, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceTypes(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceSchemaModifiedCadenceFrequency(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetGenerationCadenceRefreshFrequency(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDiscoveryConfigTargetsCloudSqlTargetDisabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 { + return nil, nil + } + + if l[0] == nil { + transformed := make(map[string]interface{}) + return transformed, nil + } + transformed := make(map[string]interface{}) + + return transformed, nil +} + func expandDataLossPreventionDiscoveryConfigStatus(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_generated_test.go b/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_generated_test.go index bdc28c6b29b..b4f85671ee2 100644 --- a/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_generated_test.go +++ b/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_generated_test.go @@ -454,6 +454,115 @@ resource "google_data_loss_prevention_inspect_template" "basic" { `, context) } +func TestAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigCloudSqlExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataLossPreventionDiscoveryConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigCloudSqlExample(context), + }, + { + ResourceName: "google_data_loss_prevention_discovery_config.cloud_sql", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "location"}, + }, + }, + }) +} + +func testAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigCloudSqlExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_data_loss_prevention_discovery_config" "cloud_sql" { + parent = "projects/%{project}/locations/us" + location = "us" + status = "RUNNING" + + targets { + cloud_sql_target { + filter { + collection { + include_regexes { + patterns { + project_id_regex = ".*" + instance_regex = ".*" + database_regex = ".*" + database_resource_name_regex = "mytable.*" + } + } + } + } + conditions { + database_engines = ["ALL_SUPPORTED_DATABASE_ENGINES"] + types = ["DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES"] + } + generation_cadence { + schema_modified_cadence { + types = ["NEW_COLUMNS", "REMOVED_COLUMNS"] + frequency = "UPDATE_FREQUENCY_DAILY" + } + refresh_frequency = "UPDATE_FREQUENCY_MONTHLY" + } + } + } + targets { + cloud_sql_target { + filter { + collection { + include_regexes { + patterns { + project_id_regex = ".*" + instance_regex = ".*" + database_regex = "do-not-scan.*" + database_resource_name_regex = ".*" + } + } + } + } + disabled {} + } + } + targets { + cloud_sql_target { + filter { + others {} + } + generation_cadence { + schema_modified_cadence { + types = ["NEW_COLUMNS"] + frequency = "UPDATE_FREQUENCY_MONTHLY" + } + refresh_frequency = "UPDATE_FREQUENCY_MONTHLY" + } + } + + } + inspect_templates = ["projects/%{project}/inspectTemplates/${google_data_loss_prevention_inspect_template.basic.name}"] +} + +resource "google_data_loss_prevention_inspect_template" "basic" { + parent = "projects/%{project}" + description = "My description" + display_name = "display_name" + + inspect_config { + info_types { + name = "EMAIL_ADDRESS" + } + } +} +`, context) +} + func testAccCheckDataLossPreventionDiscoveryConfigDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go b/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go index e34f6bcdab4..6ce325a2df2 100644 --- a/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go +++ b/google/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go @@ -17,6 +17,7 @@ func TestAccDataLossPreventionDiscoveryConfig_Update(t *testing.T) { "actions": testAccDataLossPreventionDiscoveryConfig_ActionsUpdate, "conditions": testAccDataLossPreventionDiscoveryConfig_ConditionsCadenceUpdate, "filter": testAccDataLossPreventionDiscoveryConfig_FilterUpdate, + "cloud_sql": testAccDataLossPreventionDiscoveryConfig_CloudSqlUpdate, } for name, tc := range testCases { // shadow the tc variable into scope so that when @@ -215,6 +216,41 @@ func testAccDataLossPreventionDiscoveryConfig_FilterUpdate(t *testing.T) { }) } +func testAccDataLossPreventionDiscoveryConfig_CloudSqlUpdate(t *testing.T) { + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "location": envvar.GetTestRegionFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataLossPreventionDiscoveryConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigStartCloudSql(context), + }, + { + ResourceName: "google_data_loss_prevention_discovery_config.basic", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "parent", "last_run_time", "update_time"}, + }, + { + Config: testAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigUpdateCloudSql(context), + }, + { + ResourceName: "google_data_loss_prevention_discovery_config.basic", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "parent", "last_run_time", "update_time"}, + }, + }, + }) +} + func testAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigStart(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_data_loss_prevention_inspect_template" "basic" { @@ -328,7 +364,7 @@ resource "google_data_loss_prevention_discovery_config" "basic" { actions { export_data { profile_table { - project_id = "project" + project_id = "%{project}" dataset_id = "dataset" table_id = "table" } @@ -586,3 +622,121 @@ resource "google_data_loss_prevention_discovery_config" "basic" { } `, context) } + +func testAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigStartCloudSql(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_data_loss_prevention_inspect_template" "basic" { + parent = "projects/%{project}" + description = "Description" + display_name = "Display" + inspect_config { + info_types { + name = "EMAIL_ADDRESS" + } + } +} +resource "google_data_loss_prevention_discovery_config" "basic" { + parent = "projects/%{project}/locations/%{location}" + location = "%{location}" + status = "RUNNING" + targets { + cloud_sql_target { + filter { + collection { + include_regexes { + patterns { + project_id_regex = ".*" + instance_regex = ".*" + database_regex = "do-not-scan.*" + database_resource_name_regex = ".*" + } + } + } + } + conditions { + database_engines = ["MYSQL", "POSTGRES"] + types = ["DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES"] + } + disabled {} + } + } + targets { + cloud_sql_target { + filter { + others {} + } + generation_cadence { + schema_modified_cadence { + types = ["NEW_COLUMNS"] + frequency = "UPDATE_FREQUENCY_MONTHLY" + } + refresh_frequency = "UPDATE_FREQUENCY_MONTHLY" + } + } + } + inspect_templates = ["projects/%{project}/inspectTemplates/${google_data_loss_prevention_inspect_template.basic.name}"] +} +`, context) +} + +func testAccDataLossPreventionDiscoveryConfig_dlpDiscoveryConfigUpdateCloudSql(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_data_loss_prevention_inspect_template" "basic" { + parent = "projects/%{project}" + description = "Description" + display_name = "Display" + inspect_config { + info_types { + name = "EMAIL_ADDRESS" + } + } +} +resource "google_data_loss_prevention_discovery_config" "basic" { + parent = "projects/%{project}/locations/%{location}" + location = "%{location}" + status = "RUNNING" + targets { + cloud_sql_target { + filter { + collection { + include_regexes { + patterns { + project_id_regex = ".*" + instance_regex = ".*" + database_regex = ".*" + database_resource_name_regex = "mytable.*" + } + } + } + } + conditions { + database_engines = ["ALL_SUPPORTED_DATABASE_ENGINES"] + types = ["DATABASE_RESOURCE_TYPE_TABLE"] + } + generation_cadence { + schema_modified_cadence { + types = ["NEW_COLUMNS", "REMOVED_COLUMNS"] + frequency = "UPDATE_FREQUENCY_DAILY" + } + refresh_frequency = "UPDATE_FREQUENCY_MONTHLY" + } + } + } + targets { + cloud_sql_target { + filter { + others {} + } + generation_cadence { + schema_modified_cadence { + types = ["NEW_COLUMNS", "REMOVED_COLUMNS"] + frequency = "UPDATE_FREQUENCY_DAILY" + } + refresh_frequency = "UPDATE_FREQUENCY_DAILY" + } + } + } + inspect_templates = ["projects/%{project}/inspectTemplates/${google_data_loss_prevention_inspect_template.basic.name}"] +} +`, context) +} diff --git a/website/docs/r/data_loss_prevention_discovery_config.html.markdown b/website/docs/r/data_loss_prevention_discovery_config.html.markdown index 9440b74b32e..8dfbd044639 100644 --- a/website/docs/r/data_loss_prevention_discovery_config.html.markdown +++ b/website/docs/r/data_loss_prevention_discovery_config.html.markdown @@ -292,6 +292,89 @@ resource "google_data_loss_prevention_inspect_template" "basic" { } } ``` +## Example Usage - Dlp Discovery Config Cloud Sql + + +```hcl +resource "google_data_loss_prevention_discovery_config" "cloud_sql" { + parent = "projects/my-project-name/locations/us" + location = "us" + status = "RUNNING" + + targets { + cloud_sql_target { + filter { + collection { + include_regexes { + patterns { + project_id_regex = ".*" + instance_regex = ".*" + database_regex = ".*" + database_resource_name_regex = "mytable.*" + } + } + } + } + conditions { + database_engines = ["ALL_SUPPORTED_DATABASE_ENGINES"] + types = ["DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES"] + } + generation_cadence { + schema_modified_cadence { + types = ["NEW_COLUMNS", "REMOVED_COLUMNS"] + frequency = "UPDATE_FREQUENCY_DAILY" + } + refresh_frequency = "UPDATE_FREQUENCY_MONTHLY" + } + } + } + targets { + cloud_sql_target { + filter { + collection { + include_regexes { + patterns { + project_id_regex = ".*" + instance_regex = ".*" + database_regex = "do-not-scan.*" + database_resource_name_regex = ".*" + } + } + } + } + disabled {} + } + } + targets { + cloud_sql_target { + filter { + others {} + } + generation_cadence { + schema_modified_cadence { + types = ["NEW_COLUMNS"] + frequency = "UPDATE_FREQUENCY_MONTHLY" + } + refresh_frequency = "UPDATE_FREQUENCY_MONTHLY" + } + } + + } + inspect_templates = ["projects/%{project}/inspectTemplates/${google_data_loss_prevention_inspect_template.basic.name}"] +} + +resource "google_data_loss_prevention_inspect_template" "basic" { + parent = "projects/my-project-name" + description = "My description" + display_name = "display_name" + + inspect_config { + info_types { + name = "EMAIL_ADDRESS" + } + } +} +``` ## Argument Reference @@ -460,6 +543,11 @@ The following arguments are supported: BigQuery target for Discovery. The first target to match a table will be the one applied. Structure is [documented below](#nested_big_query_target). +* `cloud_sql_target` - + (Optional) + Cloud SQL target for Discovery. The first target to match a table will be the one applied. + Structure is [documented below](#nested_cloud_sql_target). + The `big_query_target` block supports: @@ -601,6 +689,111 @@ The following arguments are supported: How frequently data profiles can be updated when tables are modified. Defaults to never. Possible values are: `UPDATE_FREQUENCY_NEVER`, `UPDATE_FREQUENCY_DAILY`, `UPDATE_FREQUENCY_MONTHLY`. +The `cloud_sql_target` block supports: + +* `filter` - + (Required) + Required. The tables the discovery cadence applies to. The first target with a matching filter will be the one to apply to a table. + Structure is [documented below](#nested_filter). + +* `conditions` - + (Optional) + In addition to matching the filter, these conditions must be true before a profile is generated. + Structure is [documented below](#nested_conditions). + +* `generation_cadence` - + (Optional) + How often and when to update profiles. New tables that match both the filter and conditions are scanned as quickly as possible depending on system capacity. + Structure is [documented below](#nested_generation_cadence). + +* `disabled` - + (Optional) + Disable profiling for database resources that match this filter. + + +The `filter` block supports: + +* `collection` - + (Optional) + A specific set of database resources for this filter to apply to. + Structure is [documented below](#nested_collection). + +* `others` - + (Optional) + Catch-all. This should always be the last target in the list because anything above it will apply first. Should only appear once in a configuration. If none is specified, a default one will be added automatically. + + +The `collection` block supports: + +* `include_regexes` - + (Optional) + A collection of regular expressions to match a database resource against. + Structure is [documented below](#nested_include_regexes). + + +The `include_regexes` block supports: + +* `patterns` - + (Optional) + A group of regular expression patterns to match against one or more database resources. Maximum of 100 entries. The sum of all regular expressions' length can't exceed 10 KiB. + Structure is [documented below](#nested_patterns). + + +The `patterns` block supports: + +* `project_id_regex` - + (Optional) + For organizations, if unset, will match all projects. Has no effect for data profile configurations created within a project. + +* `instance_regex` - + (Optional) + Regex to test the instance name against. If empty, all instances match. + +* `database_regex` - + (Optional) + Regex to test the database name against. If empty, all databases match. + +* `database_resource_name_regex` - + (Optional) + Regex to test the database resource's name against. An example of a database resource name is a table's name. Other database resource names like view names could be included in the future. If empty, all database resources match.' + +The `conditions` block supports: + +* `database_engines` - + (Optional) + Database engines that should be profiled. Optional. Defaults to ALL_SUPPORTED_DATABASE_ENGINES if unspecified. + Each value may be one of: `ALL_SUPPORTED_DATABASE_ENGINES`, `MYSQL`, `POSTGRES`. + +* `types` - + (Optional) + Data profiles will only be generated for the database resource types specified in this field. If not specified, defaults to [DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES]. + Each value may be one of: `DATABASE_RESOURCE_TYPE_ALL_SUPPORTED_TYPES`, `DATABASE_RESOURCE_TYPE_TABLE`. + +The `generation_cadence` block supports: + +* `schema_modified_cadence` - + (Optional) + Governs when to update data profiles when a schema is modified + Structure is [documented below](#nested_schema_modified_cadence). + +* `refresh_frequency` - + (Optional) + Data changes (non-schema changes) in Cloud SQL tables can't trigger reprofiling. If you set this field, profiles are refreshed at this frequency regardless of whether the underlying tables have changes. Defaults to never. + Possible values are: `UPDATE_FREQUENCY_NEVER`, `UPDATE_FREQUENCY_DAILY`, `UPDATE_FREQUENCY_MONTHLY`. + + +The `schema_modified_cadence` block supports: + +* `types` - + (Optional) + The types of schema modifications to consider. Defaults to NEW_COLUMNS. + Each value may be one of: `NEW_COLUMNS`, `REMOVED_COLUMNS`. + +* `frequency` - + (Optional) + Frequency to regenerate data profiles when the schema is modified. Defaults to monthly. + Possible values are: `UPDATE_FREQUENCY_NEVER`, `UPDATE_FREQUENCY_DAILY`, `UPDATE_FREQUENCY_MONTHLY`. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: