diff --git a/.changelog/3931.txt b/.changelog/3931.txt new file mode 100644 index 00000000000..eefcecd643f --- /dev/null +++ b/.changelog/3931.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +google_data_loss_prevention_deidentify_template +``` diff --git a/google/provider.go b/google/provider.go index ed28144bda2..98318e296be 100644 --- a/google/provider.go +++ b/google/provider.go @@ -638,9 +638,9 @@ func Provider() *schema.Provider { return provider } -// Generated resources: 159 +// Generated resources: 160 // Generated IAM resources: 69 -// Total generated resources: 228 +// Total generated resources: 229 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -776,6 +776,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_data_loss_prevention_job_trigger": resourceDataLossPreventionJobTrigger(), "google_data_loss_prevention_inspect_template": resourceDataLossPreventionInspectTemplate(), "google_data_loss_prevention_stored_info_type": resourceDataLossPreventionStoredInfoType(), + "google_data_loss_prevention_deidentify_template": resourceDataLossPreventionDeidentifyTemplate(), "google_dataproc_autoscaling_policy": resourceDataprocAutoscalingPolicy(), "google_datastore_index": resourceDatastoreIndex(), "google_deployment_manager_deployment": resourceDeploymentManagerDeployment(), diff --git a/google/resource_data_loss_prevention_deidentify_template.go b/google/resource_data_loss_prevention_deidentify_template.go new file mode 100644 index 00000000000..262b337de99 --- /dev/null +++ b/google/resource_data_loss_prevention_deidentify_template.go @@ -0,0 +1,1369 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "log" + "reflect" + "strconv" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceDataLossPreventionDeidentifyTemplate() *schema.Resource { + return &schema.Resource{ + Create: resourceDataLossPreventionDeidentifyTemplateCreate, + Read: resourceDataLossPreventionDeidentifyTemplateRead, + Update: resourceDataLossPreventionDeidentifyTemplateUpdate, + Delete: resourceDataLossPreventionDeidentifyTemplateDelete, + + Importer: &schema.ResourceImporter{ + State: resourceDataLossPreventionDeidentifyTemplateImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(4 * time.Minute), + Update: schema.DefaultTimeout(4 * time.Minute), + Delete: schema.DefaultTimeout(4 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "deidentify_config": { + Type: schema.TypeList, + Required: true, + Description: `Configuration of the deidentify template`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "info_type_transformations": { + Type: schema.TypeList, + Required: true, + Description: `Specifies free-text based transformations to be applied to the dataset.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "transformations": { + Type: schema.TypeList, + Required: true, + Description: `Transformation for each infoType. Cannot specify more than one for a given infoType.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "primitive_transformation": { + Type: schema.TypeList, + Required: true, + Description: `Primitive transformation to apply to the infoType.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "character_mask_config": { + Type: schema.TypeList, + Optional: true, + Description: `Partially mask a string by replacing a given number of characters with a fixed character. +Masking can start from the beginning or end of the string.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "characters_to_ignore": { + Type: schema.TypeList, + Optional: true, + Description: `Characters to skip when doing deidentification of a value. These will be left alone and skipped.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "character_to_skip": { + Type: schema.TypeString, + Optional: true, + Description: `Characters to not transform when masking.`, + }, + "common_characters_to_ignore": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"NUMERIC", "ALPHA_UPPER_CASE", "ALPHA_LOWER_CASE", "PUNCTUATION", "WHITESPACE", ""}, false), + Description: `Common characters to not transform when masking. Useful to avoid removing punctuation. Possible values: ["NUMERIC", "ALPHA_UPPER_CASE", "ALPHA_LOWER_CASE", "PUNCTUATION", "WHITESPACE"]`, + }, + }, + }, + }, + "masking_character": { + Type: schema.TypeString, + Optional: true, + Description: `Character to use to mask the sensitive values—for example, * for an alphabetic string such as a name, or 0 for a numeric string +such as ZIP code or credit card number. This string must have a length of 1. If not supplied, this value defaults to * for +strings, and 0 for digits.`, + }, + "number_to_mask": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of characters to mask. If not set, all matching chars will be masked. Skipped characters do not count towards this tally.`, + }, + "reverse_order": { + Type: schema.TypeBool, + Optional: true, + Description: `Mask characters in reverse order. For example, if masking_character is 0, number_to_mask is 14, and reverse_order is 'false', then the +input string '1234-5678-9012-3456' is masked as '00000000000000-3456'.`, + }, + }, + }, + }, + "replace_config": { + Type: schema.TypeList, + Optional: true, + Description: `Replace each input value with a given value.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "new_value": { + Type: schema.TypeList, + Required: true, + Description: `Replace each input value with a given value.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "boolean_value": { + Type: schema.TypeBool, + Optional: true, + Description: `A boolean value.`, + }, + "date_value": { + Type: schema.TypeList, + Optional: true, + Description: `Represents a whole or partial calendar date.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "day": { + Type: schema.TypeInt, + Optional: true, + Description: `Day of month. Must be from 1 to 31 and valid for the year and month, or 0 if specifying a +year by itself or a year and month where the day is not significant.`, + }, + "month": { + Type: schema.TypeInt, + Optional: true, + Description: `Month of year. Must be from 1 to 12, or 0 if specifying a year without a month and day.`, + }, + "year": { + Type: schema.TypeInt, + Optional: true, + Description: `Year of date. Must be from 1 to 9999, or 0 if specifying a date without a year.`, + }, + }, + }, + }, + "day_of_week_value": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY", ""}, false), + Description: `Represents a day of the week. Possible values: ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"]`, + }, + "float_value": { + Type: schema.TypeFloat, + Optional: true, + Description: `A float value.`, + }, + "integer_value": { + Type: schema.TypeInt, + Optional: true, + Description: `An integer value.`, + }, + "string_value": { + Type: schema.TypeString, + Optional: true, + Description: `A string value.`, + }, + "time_value": { + Type: schema.TypeList, + Optional: true, + Description: `Represents a time of day.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hours": { + Type: schema.TypeInt, + Optional: true, + Description: `Hours of day in 24 hour format. Should be from 0 to 23.`, + }, + "minutes": { + Type: schema.TypeInt, + Optional: true, + Description: `Minutes of hour of day. Must be from 0 to 59.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + Description: `Fractions of seconds in nanoseconds. Must be from 0 to 999,999,999.`, + }, + "seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Seconds of minutes of the time. Must normally be from 0 to 59.`, + }, + }, + }, + }, + "timestamp_value": { + Type: schema.TypeString, + Optional: true, + Description: `A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. +Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "info_types": { + Type: schema.TypeList, + Optional: true, + Description: `InfoTypes to apply the transformation to. Leaving this empty will apply the transformation to apply to +all findings that correspond to infoTypes that were requested in InspectConfig.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of the information type.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "parent": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The parent of the template in any of the following formats: + +* 'projects/{{project}}' +* 'projects/{{project}}/locations/{{location}}' +* 'organizations/{{organization_id}}' +* 'organizations/{{organization_id}}/locations/{{location}}'`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `A description of the template.`, + }, + "display_name": { + Type: schema.TypeString, + Optional: true, + Description: `User set display name of the template.`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The resource name of the template. Set by the server.`, + }, + }, + } +} + +func resourceDataLossPreventionDeidentifyTemplateCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + descriptionProp, err := expandDataLossPreventionDeidentifyTemplateDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + displayNameProp, err := expandDataLossPreventionDeidentifyTemplateDisplayName(d.Get("display_name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("display_name"); !isEmptyValue(reflect.ValueOf(displayNameProp)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { + obj["displayName"] = displayNameProp + } + deidentifyConfigProp, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfig(d.Get("deidentify_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("deidentify_config"); !isEmptyValue(reflect.ValueOf(deidentifyConfigProp)) && (ok || !reflect.DeepEqual(v, deidentifyConfigProp)) { + obj["deidentifyConfig"] = deidentifyConfigProp + } + + obj, err = resourceDataLossPreventionDeidentifyTemplateEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{DataLossPreventionBasePath}}{{parent}}/deidentifyTemplates") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new DeidentifyTemplate: %#v", obj) + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating DeidentifyTemplate: %s", err) + } + if err := d.Set("name", flattenDataLossPreventionDeidentifyTemplateName(res["name"], d, config)); err != nil { + return fmt.Errorf(`Error setting computed identity field "name": %s`, err) + } + + // Store the ID now + id, err := replaceVars(d, config, "{{parent}}/deidentifyTemplates/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating DeidentifyTemplate %q: %#v", d.Id(), res) + + return resourceDataLossPreventionDeidentifyTemplateRead(d, meta) +} + +func resourceDataLossPreventionDeidentifyTemplateRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{DataLossPreventionBasePath}}{{parent}}/deidentifyTemplates/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequest(config, "GET", billingProject, url, userAgent, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("DataLossPreventionDeidentifyTemplate %q", d.Id())) + } + + if err := d.Set("name", flattenDataLossPreventionDeidentifyTemplateName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading DeidentifyTemplate: %s", err) + } + if err := d.Set("description", flattenDataLossPreventionDeidentifyTemplateDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading DeidentifyTemplate: %s", err) + } + if err := d.Set("display_name", flattenDataLossPreventionDeidentifyTemplateDisplayName(res["displayName"], d, config)); err != nil { + return fmt.Errorf("Error reading DeidentifyTemplate: %s", err) + } + if err := d.Set("deidentify_config", flattenDataLossPreventionDeidentifyTemplateDeidentifyConfig(res["deidentifyConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading DeidentifyTemplate: %s", err) + } + + return nil +} + +func resourceDataLossPreventionDeidentifyTemplateUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + config.userAgent = userAgent + + billingProject := "" + + obj := make(map[string]interface{}) + descriptionProp, err := expandDataLossPreventionDeidentifyTemplateDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + displayNameProp, err := expandDataLossPreventionDeidentifyTemplateDisplayName(d.Get("display_name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("display_name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { + obj["displayName"] = displayNameProp + } + deidentifyConfigProp, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfig(d.Get("deidentify_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("deidentify_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, deidentifyConfigProp)) { + obj["deidentifyConfig"] = deidentifyConfigProp + } + + obj, err = resourceDataLossPreventionDeidentifyTemplateEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{DataLossPreventionBasePath}}{{parent}}/deidentifyTemplates/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating DeidentifyTemplate %q: %#v", d.Id(), obj) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("display_name") { + updateMask = append(updateMask, "displayName") + } + + if d.HasChange("deidentify_config") { + updateMask = append(updateMask, "deidentifyConfig") + } + // updateMask is a URL parameter but not present in the schema, so replaceVars + // won't set it + url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "PATCH", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return fmt.Errorf("Error updating DeidentifyTemplate %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating DeidentifyTemplate %q: %#v", d.Id(), res) + } + + return resourceDataLossPreventionDeidentifyTemplateRead(d, meta) +} + +func resourceDataLossPreventionDeidentifyTemplateDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + config.userAgent = userAgent + + billingProject := "" + + url, err := replaceVars(d, config, "{{DataLossPreventionBasePath}}{{parent}}/deidentifyTemplates/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting DeidentifyTemplate %q", d.Id()) + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "DELETE", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "DeidentifyTemplate") + } + + log.Printf("[DEBUG] Finished deleting DeidentifyTemplate %q: %#v", d.Id(), res) + return nil +} + +func resourceDataLossPreventionDeidentifyTemplateImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + + // Custom import to handle parent possibilities + if err := parseImportId([]string{"(?P.+)"}, d, config); err != nil { + return nil, err + } + parts := strings.Split(d.Get("name").(string), "/") + if len(parts) == 6 { + if err := d.Set("name", parts[5]); err != nil { + return nil, fmt.Errorf("Error setting name: %s", err) + } + } else if len(parts) == 4 { + if err := d.Set("name", parts[3]); err != nil { + return nil, fmt.Errorf("Error setting name: %s", err) + } + } else { + return nil, fmt.Errorf("Unexpected import id: %s, expected form {{parent}}/deidentifyTemplate/{{name}}", d.Get("name").(string)) + } + // Remove "/deidentifyTemplate/{{name}}" from the id + parts = parts[:len(parts)-2] + if err := d.Set("parent", strings.Join(parts, "/")); err != nil { + return nil, fmt.Errorf("Error setting parent: %s", err) + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "{{parent}}/deidentifyTemplates/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenDataLossPreventionDeidentifyTemplateName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + return NameFromSelfLinkStateFunc(v) +} + +func flattenDataLossPreventionDeidentifyTemplateDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDisplayName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["info_type_transformations"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformations(original["infoTypeTransformations"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformations(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["transformations"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformations(original["transformations"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformations(v interface{}, d *schema.ResourceData, config *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{}{ + "info_types": flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypes(original["infoTypes"], d, config), + "primitive_transformation": flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformation(original["primitiveTransformation"], d, config), + }) + } + return transformed +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypes(v interface{}, d *schema.ResourceData, config *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{}{ + "name": flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypesName(original["name"], d, config), + }) + } + return transformed +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypesName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformation(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["replace_config"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfig(original["replaceConfig"], d, config) + transformed["character_mask_config"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfig(original["characterMaskConfig"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["new_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValue(original["newValue"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["integer_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueIntegerValue(original["integerValue"], d, config) + transformed["float_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueFloatValue(original["floatValue"], d, config) + transformed["string_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueStringValue(original["stringValue"], d, config) + transformed["boolean_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueBooleanValue(original["booleanValue"], d, config) + transformed["timestamp_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimestampValue(original["timestampValue"], d, config) + transformed["time_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValue(original["timeValue"], d, config) + transformed["date_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValue(original["dateValue"], d, config) + transformed["day_of_week_value"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDayOfWeekValue(original["dayOfWeekValue"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueIntegerValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueFloatValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueStringValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueBooleanValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimestampValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["hours"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueHours(original["hours"], d, config) + transformed["minutes"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueMinutes(original["minutes"], d, config) + transformed["seconds"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueSeconds(original["seconds"], d, config) + transformed["nanos"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueNanos(original["nanos"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueHours(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueMinutes(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueSeconds(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueNanos(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["year"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueYear(original["year"], d, config) + transformed["month"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueMonth(original["month"], d, config) + transformed["day"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueDay(original["day"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueYear(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueMonth(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueDay(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDayOfWeekValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["masking_character"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigMaskingCharacter(original["maskingCharacter"], d, config) + transformed["number_to_mask"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigNumberToMask(original["numberToMask"], d, config) + transformed["reverse_order"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigReverseOrder(original["reverseOrder"], d, config) + transformed["characters_to_ignore"] = + flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnore(original["charactersToIgnore"], d, config) + return []interface{}{transformed} +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigMaskingCharacter(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigNumberToMask(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigReverseOrder(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnore(v interface{}, d *schema.ResourceData, config *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{}{ + "character_to_skip": flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCharacterToSkip(original["characterToSkip"], d, config), + "common_characters_to_ignore": flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCommonCharactersToIgnore(original["commonCharactersToIgnore"], d, config), + }) + } + return transformed +} +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCharacterToSkip(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCommonCharactersToIgnore(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func expandDataLossPreventionDeidentifyTemplateDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDisplayName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfig(v interface{}, d TerraformResourceData, config *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{}) + + transformedInfoTypeTransformations, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformations(original["info_type_transformations"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInfoTypeTransformations); val.IsValid() && !isEmptyValue(val) { + transformed["infoTypeTransformations"] = transformedInfoTypeTransformations + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformations(v interface{}, d TerraformResourceData, config *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{}) + + transformedTransformations, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformations(original["transformations"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTransformations); val.IsValid() && !isEmptyValue(val) { + transformed["transformations"] = transformedTransformations + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformations(v interface{}, d TerraformResourceData, config *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{}) + + transformedInfoTypes, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypes(original["info_types"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInfoTypes); val.IsValid() && !isEmptyValue(val) { + transformed["infoTypes"] = transformedInfoTypes + } + + transformedPrimitiveTransformation, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformation(original["primitive_transformation"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrimitiveTransformation); val.IsValid() && !isEmptyValue(val) { + transformed["primitiveTransformation"] = transformedPrimitiveTransformation + } + + req = append(req, transformed) + } + return req, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypes(v interface{}, d TerraformResourceData, config *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{}) + + transformedName, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypesName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { + transformed["name"] = transformedName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsInfoTypesName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformation(v interface{}, d TerraformResourceData, config *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{}) + + transformedReplaceConfig, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfig(original["replace_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReplaceConfig); val.IsValid() && !isEmptyValue(val) { + transformed["replaceConfig"] = transformedReplaceConfig + } + + transformedCharacterMaskConfig, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfig(original["character_mask_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCharacterMaskConfig); val.IsValid() && !isEmptyValue(val) { + transformed["characterMaskConfig"] = transformedCharacterMaskConfig + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfig(v interface{}, d TerraformResourceData, config *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{}) + + transformedNewValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValue(original["new_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNewValue); val.IsValid() && !isEmptyValue(val) { + transformed["newValue"] = transformedNewValue + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValue(v interface{}, d TerraformResourceData, config *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{}) + + transformedIntegerValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueIntegerValue(original["integer_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIntegerValue); val.IsValid() && !isEmptyValue(val) { + transformed["integerValue"] = transformedIntegerValue + } + + transformedFloatValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueFloatValue(original["float_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFloatValue); val.IsValid() && !isEmptyValue(val) { + transformed["floatValue"] = transformedFloatValue + } + + transformedStringValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueStringValue(original["string_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedStringValue); val.IsValid() && !isEmptyValue(val) { + transformed["stringValue"] = transformedStringValue + } + + transformedBooleanValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueBooleanValue(original["boolean_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedBooleanValue); val.IsValid() && !isEmptyValue(val) { + transformed["booleanValue"] = transformedBooleanValue + } + + transformedTimestampValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimestampValue(original["timestamp_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTimestampValue); val.IsValid() && !isEmptyValue(val) { + transformed["timestampValue"] = transformedTimestampValue + } + + transformedTimeValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValue(original["time_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTimeValue); val.IsValid() && !isEmptyValue(val) { + transformed["timeValue"] = transformedTimeValue + } + + transformedDateValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValue(original["date_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDateValue); val.IsValid() && !isEmptyValue(val) { + transformed["dateValue"] = transformedDateValue + } + + transformedDayOfWeekValue, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDayOfWeekValue(original["day_of_week_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDayOfWeekValue); val.IsValid() && !isEmptyValue(val) { + transformed["dayOfWeekValue"] = transformedDayOfWeekValue + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueIntegerValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueFloatValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueStringValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueBooleanValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimestampValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValue(v interface{}, d TerraformResourceData, config *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{}) + + transformedHours, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueHours(original["hours"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHours); val.IsValid() && !isEmptyValue(val) { + transformed["hours"] = transformedHours + } + + transformedMinutes, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueMinutes(original["minutes"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMinutes); val.IsValid() && !isEmptyValue(val) { + transformed["minutes"] = transformedMinutes + } + + transformedSeconds, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueSeconds(original["seconds"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !isEmptyValue(val) { + transformed["seconds"] = transformedSeconds + } + + transformedNanos, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueNanos(original["nanos"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !isEmptyValue(val) { + transformed["nanos"] = transformedNanos + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueHours(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueMinutes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueSeconds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueTimeValueNanos(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValue(v interface{}, d TerraformResourceData, config *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{}) + + transformedYear, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueYear(original["year"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedYear); val.IsValid() && !isEmptyValue(val) { + transformed["year"] = transformedYear + } + + transformedMonth, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueMonth(original["month"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMonth); val.IsValid() && !isEmptyValue(val) { + transformed["month"] = transformedMonth + } + + transformedDay, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueDay(original["day"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDay); val.IsValid() && !isEmptyValue(val) { + transformed["day"] = transformedDay + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueYear(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueMonth(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDateValueDay(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationReplaceConfigNewValueDayOfWeekValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfig(v interface{}, d TerraformResourceData, config *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{}) + + transformedMaskingCharacter, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigMaskingCharacter(original["masking_character"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMaskingCharacter); val.IsValid() && !isEmptyValue(val) { + transformed["maskingCharacter"] = transformedMaskingCharacter + } + + transformedNumberToMask, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigNumberToMask(original["number_to_mask"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNumberToMask); val.IsValid() && !isEmptyValue(val) { + transformed["numberToMask"] = transformedNumberToMask + } + + transformedReverseOrder, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigReverseOrder(original["reverse_order"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReverseOrder); val.IsValid() && !isEmptyValue(val) { + transformed["reverseOrder"] = transformedReverseOrder + } + + transformedCharactersToIgnore, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnore(original["characters_to_ignore"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCharactersToIgnore); val.IsValid() && !isEmptyValue(val) { + transformed["charactersToIgnore"] = transformedCharactersToIgnore + } + + return transformed, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigMaskingCharacter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigNumberToMask(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigReverseOrder(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnore(v interface{}, d TerraformResourceData, config *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{}) + + transformedCharacterToSkip, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCharacterToSkip(original["character_to_skip"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCharacterToSkip); val.IsValid() && !isEmptyValue(val) { + transformed["characterToSkip"] = transformedCharacterToSkip + } + + transformedCommonCharactersToIgnore, err := expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCommonCharactersToIgnore(original["common_characters_to_ignore"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCommonCharactersToIgnore); val.IsValid() && !isEmptyValue(val) { + transformed["commonCharactersToIgnore"] = transformedCommonCharactersToIgnore + } + + req = append(req, transformed) + } + return req, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCharacterToSkip(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDataLossPreventionDeidentifyTemplateDeidentifyConfigInfoTypeTransformationsTransformationsPrimitiveTransformationCharacterMaskConfigCharactersToIgnoreCommonCharactersToIgnore(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func resourceDataLossPreventionDeidentifyTemplateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + newObj := make(map[string]interface{}) + newObj["deidentifyTemplate"] = obj + return newObj, nil +} diff --git a/google/resource_data_loss_prevention_deidentify_template_generated_test.go b/google/resource_data_loss_prevention_deidentify_template_generated_test.go new file mode 100644 index 00000000000..7cdf57c9a52 --- /dev/null +++ b/google/resource_data_loss_prevention_deidentify_template_generated_test.go @@ -0,0 +1,149 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": getTestProjectFromEnv(), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + }, + CheckDestroy: testAccCheckDataLossPreventionDeidentifyTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateBasicExample(context), + }, + { + ResourceName: "google_data_loss_prevention_deidentify_template.basic", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + }, + }) +} + +func testAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateBasicExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_deidentify_template" "basic" { + parent = "projects/%{project}" + description = "Description" + display_name = "Displayname" + + deidentify_config { + info_type_transformations { + transformations { + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "CREDIT_CARD_NUMBER" + } + + primitive_transformation { + replace_config { + new_value { + integer_value = 9 + } + } + } + } + + transformations { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "LAST_NAME" + } + + primitive_transformation { + character_mask_config { + masking_character = "X" + number_to_mask = 4 + reverse_order = true + characters_to_ignore { + common_characters_to_ignore = "PUNCTUATION" + } + } + } + } + + transformations { + info_types { + name = "DATE_OF_BIRTH" + } + + primitive_transformation { + replace_config { + new_value { + date_value { + year = 2020 + month = 1 + day = 1 + } + } + } + } + } + } + } +} +`, context) +} + +func testAccCheckDataLossPreventionDeidentifyTemplateDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_data_loss_prevention_deidentify_template" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + url, err := replaceVarsForTest(config, rs, "{{DataLossPreventionBasePath}}{{parent}}/deidentifyTemplates/{{name}}") + if err != nil { + return err + } + + _, err = sendRequest(config, "GET", "", url, config.userAgent, nil) + if err == nil { + return fmt.Errorf("DataLossPreventionDeidentifyTemplate still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/resource_data_loss_prevention_deidentify_template_sweeper_test.go b/google/resource_data_loss_prevention_deidentify_template_sweeper_test.go new file mode 100644 index 00000000000..944f6b8806c --- /dev/null +++ b/google/resource_data_loss_prevention_deidentify_template_sweeper_test.go @@ -0,0 +1,124 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func init() { + resource.AddTestSweepers("DataLossPreventionDeidentifyTemplate", &resource.Sweeper{ + Name: "DataLossPreventionDeidentifyTemplate", + F: testSweepDataLossPreventionDeidentifyTemplate, + }) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepDataLossPreventionDeidentifyTemplate(region string) error { + resourceName := "DataLossPreventionDeidentifyTemplate" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := getTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://dlp.googleapis.com/v2/{{parent}}/deidentifyTemplates", "?")[0] + listUrl, err := replaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := sendRequest(config, "GET", config.Project, listUrl, config.userAgent, nil) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["deidentifyTemplates"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !isSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://dlp.googleapis.com/v2/{{parent}}/deidentifyTemplates/{{name}}" + deleteUrl, err := replaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = sendRequest(config, "DELETE", config.Project, deleteUrl, config.userAgent, nil) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/google/resource_data_loss_prevention_deidentify_template_test.go b/google/resource_data_loss_prevention_deidentify_template_test.go new file mode 100644 index 00000000000..257f4bca3d7 --- /dev/null +++ b/google/resource_data_loss_prevention_deidentify_template_test.go @@ -0,0 +1,171 @@ +package google + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "organization": getTestOrgFromEnv(t), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDataLossPreventionDeidentifyTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateStart(context), + }, + { + ResourceName: "google_data_loss_prevention_deidentify_template.basic", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateUpdate(context), + }, + { + ResourceName: "google_data_loss_prevention_deidentify_template.basic", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateStart(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_deidentify_template" "basic" { + parent = "organizations/%{organization}" + description = "Description" + display_name = "Displayname" + + deidentify_config { + info_type_transformations { + transformations { + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "CREDIT_CARD_NUMBER" + } + + primitive_transformation { + replace_config { + new_value { + integer_value = 9 + } + } + } + } + + transformations { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "LAST_NAME" + } + + primitive_transformation { + character_mask_config { + masking_character = "X" + number_to_mask = 4 + reverse_order = true + characters_to_ignore { + common_characters_to_ignore = "PUNCTUATION" + } + } + } + } + + transformations { + info_types { + name = "DATE_OF_BIRTH" + } + + primitive_transformation { + replace_config { + new_value { + date_value { + year = 2020 + month = 1 + day = 1 + } + } + } + } + } + } + } +} +`, context) +} + +func testAccDataLossPreventionDeidentifyTemplate_dlpDeidentifyTemplateUpdate(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_deidentify_template" "basic" { + parent = "organizations/%{organization}" + description = "Description" + display_name = "Displayname" + + deidentify_config { + info_type_transformations { + transformations { + info_types { + name = "CREDIT_CARD_NUMBER" + } + + primitive_transformation { + replace_config { + new_value { + integer_value = 9 + } + } + } + } + + transformations { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "LAST_NAME" + } + + primitive_transformation { + character_mask_config { + number_to_mask = 3 + reverse_order = true + } + } + } + + transformations { + info_types { + name = "DATE_OF_BIRTH" + } + + primitive_transformation { + replace_config { + new_value { + date_value { + year = 2020 + month = 1 + day = 1 + } + } + } + } + } + } + } +} +`, context) +} diff --git a/website/docs/r/data_loss_prevention_deidentify_template.html.markdown b/website/docs/r/data_loss_prevention_deidentify_template.html.markdown new file mode 100644 index 00000000000..378f671d4e2 --- /dev/null +++ b/website/docs/r/data_loss_prevention_deidentify_template.html.markdown @@ -0,0 +1,330 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +subcategory: "Data loss prevention" +layout: "google" +page_title: "Google: google_data_loss_prevention_deidentify_template" +sidebar_current: "docs-google-data-loss-prevention-deidentify-template" +description: |- + Allows creation of templates to de-idenfity content. +--- + +# google\_data\_loss\_prevention\_deidentify\_template + +Allows creation of templates to de-idenfity content. + + +To get more information about DeidentifyTemplate, see: + +* [API documentation](https://cloud.google.com/dlp/docs/reference/rest/v2/projects.deidentifyTemplates) +* How-to Guides + * [Official Documentation](https://cloud.google.com/dlp/docs/concepts-templates) + +
+ + Open in Cloud Shell + +
+## Example Usage - Dlp Deidentify Template Basic + + +```hcl +resource "google_data_loss_prevention_deidentify_template" "basic" { + parent = "projects/my-project-name" + description = "Description" + display_name = "Displayname" + + deidentify_config { + info_type_transformations { + transformations { + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "CREDIT_CARD_NUMBER" + } + + primitive_transformation { + replace_config { + new_value { + integer_value = 9 + } + } + } + } + + transformations { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "LAST_NAME" + } + + primitive_transformation { + character_mask_config { + masking_character = "X" + number_to_mask = 4 + reverse_order = true + characters_to_ignore { + common_characters_to_ignore = "PUNCTUATION" + } + } + } + } + + transformations { + info_types { + name = "DATE_OF_BIRTH" + } + + primitive_transformation { + replace_config { + new_value { + date_value { + year = 2020 + month = 1 + day = 1 + } + } + } + } + } + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `deidentify_config` - + (Required) + Configuration of the deidentify template + Structure is documented below. + +* `parent` - + (Required) + The parent of the template in any of the following formats: + * `projects/{{project}}` + * `projects/{{project}}/locations/{{location}}` + * `organizations/{{organization_id}}` + * `organizations/{{organization_id}}/locations/{{location}}` + + +The `deidentify_config` block supports: + +* `info_type_transformations` - + (Required) + Specifies free-text based transformations to be applied to the dataset. + Structure is documented below. + + +The `info_type_transformations` block supports: + +* `transformations` - + (Required) + Transformation for each infoType. Cannot specify more than one for a given infoType. + Structure is documented below. + + +The `transformations` block supports: + +* `info_types` - + (Optional) + InfoTypes to apply the transformation to. Leaving this empty will apply the transformation to apply to + all findings that correspond to infoTypes that were requested in InspectConfig. + Structure is documented below. + +* `primitive_transformation` - + (Required) + Primitive transformation to apply to the infoType. + Structure is documented below. + + +The `info_types` block supports: + +* `name` - + (Required) + Name of the information type. + +The `primitive_transformation` block supports: + +* `replace_config` - + (Optional) + Replace each input value with a given value. + Structure is documented below. + +* `character_mask_config` - + (Optional) + Partially mask a string by replacing a given number of characters with a fixed character. + Masking can start from the beginning or end of the string. + Structure is documented below. + + +The `replace_config` block supports: + +* `new_value` - + (Required) + Replace each input value with a given value. + Structure is documented below. + + +The `new_value` block supports: + +* `integer_value` - + (Optional) + An integer value. + +* `float_value` - + (Optional) + A float value. + +* `string_value` - + (Optional) + A string value. + +* `boolean_value` - + (Optional) + A boolean value. + +* `timestamp_value` - + (Optional) + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. + Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + +* `time_value` - + (Optional) + Represents a time of day. + Structure is documented below. + +* `date_value` - + (Optional) + Represents a whole or partial calendar date. + Structure is documented below. + +* `day_of_week_value` - + (Optional) + Represents a day of the week. + Possible values are `MONDAY`, `TUESDAY`, `WEDNESDAY`, `THURSDAY`, `FRIDAY`, `SATURDAY`, and `SUNDAY`. + + +The `time_value` block supports: + +* `hours` - + (Optional) + Hours of day in 24 hour format. Should be from 0 to 23. + +* `minutes` - + (Optional) + Minutes of hour of day. Must be from 0 to 59. + +* `seconds` - + (Optional) + Seconds of minutes of the time. Must normally be from 0 to 59. + +* `nanos` - + (Optional) + Fractions of seconds in nanoseconds. Must be from 0 to 999,999,999. + +The `date_value` block supports: + +* `year` - + (Optional) + Year of date. Must be from 1 to 9999, or 0 if specifying a date without a year. + +* `month` - + (Optional) + Month of year. Must be from 1 to 12, or 0 if specifying a year without a month and day. + +* `day` - + (Optional) + Day of month. Must be from 1 to 31 and valid for the year and month, or 0 if specifying a + year by itself or a year and month where the day is not significant. + +The `character_mask_config` block supports: + +* `masking_character` - + (Optional) + Character to use to mask the sensitive values—for example, * for an alphabetic string such as a name, or 0 for a numeric string + such as ZIP code or credit card number. This string must have a length of 1. If not supplied, this value defaults to * for + strings, and 0 for digits. + +* `number_to_mask` - + (Optional) + Number of characters to mask. If not set, all matching chars will be masked. Skipped characters do not count towards this tally. + +* `reverse_order` - + (Optional) + Mask characters in reverse order. For example, if masking_character is 0, number_to_mask is 14, and reverse_order is `false`, then the + input string `1234-5678-9012-3456` is masked as `00000000000000-3456`. + +* `characters_to_ignore` - + (Optional) + Characters to skip when doing deidentification of a value. These will be left alone and skipped. + Structure is documented below. + + +The `characters_to_ignore` block supports: + +* `character_to_skip` - + (Optional) + Characters to not transform when masking. + +* `common_characters_to_ignore` - + (Optional) + Common characters to not transform when masking. Useful to avoid removing punctuation. + Possible values are `NUMERIC`, `ALPHA_UPPER_CASE`, `ALPHA_LOWER_CASE`, `PUNCTUATION`, and `WHITESPACE`. + +- - - + + +* `description` - + (Optional) + A description of the template. + +* `display_name` - + (Optional) + User set display name of the template. + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `{{parent}}/deidentifyTemplates/{{name}}` + +* `name` - + The resource name of the template. Set by the server. + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. + +## Import + +DeidentifyTemplate can be imported using any of these accepted formats: + +``` +$ terraform import google_data_loss_prevention_deidentify_template.default {{parent}}/deidentifyTemplates/{{name}} +$ terraform import google_data_loss_prevention_deidentify_template.default {{parent}}/{{name}} +``` diff --git a/website/google.erb b/website/google.erb index 6bfffecc70d..475f95fde6c 100644 --- a/website/google.erb +++ b/website/google.erb @@ -1638,6 +1638,10 @@ Resources