diff --git a/.changelog/6203.txt b/.changelog/6203.txt new file mode 100644 index 0000000000..123843f7f7 --- /dev/null +++ b/.changelog/6203.txt @@ -0,0 +1,6 @@ +```release-note:new-resource + `google_certificate_map_entry` +``` +```release-note:new-resource + `google_certificate_map` +``` diff --git a/google-beta/common_diff_suppress.go b/google-beta/common_diff_suppress.go index a518f9b53b..176ca49aec 100644 --- a/google-beta/common_diff_suppress.go +++ b/google-beta/common_diff_suppress.go @@ -228,7 +228,7 @@ func lastSlashDiffSuppress(_, old, new string, _ *schema.ResourceData) bool { // Suppress diffs when the value read from api // has the project number instead of the project name -func projectNumberDiffSupress(_, old, new string, _ *schema.ResourceData) bool { +func projectNumberDiffSuppress(_, old, new string, _ *schema.ResourceData) bool { var a2, b2 string reN := regexp.MustCompile("projects/\\d+") re := regexp.MustCompile("projects/[^/]+") diff --git a/google-beta/provider.go b/google-beta/provider.go index 418b4863c3..e676ceb335 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -936,9 +936,9 @@ func Provider() *schema.Provider { return provider } -// Generated resources: 253 +// Generated resources: 255 // Generated IAM resources: 165 -// Total generated resources: 418 +// Total generated resources: 420 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -1018,6 +1018,8 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_binary_authorization_policy": resourceBinaryAuthorizationPolicy(), "google_certificate_manager_dns_authorization": resourceCertificateManagerDnsAuthorization(), "google_certificate_manager_certificate": resourceCertificateManagerCertificate(), + "google_certificate_manager_certificate_map": resourceCertificateManagerCertificateMap(), + "google_certificate_manager_certificate_map_entry": resourceCertificateManagerCertificateMapEntry(), "google_cloud_asset_project_feed": resourceCloudAssetProjectFeed(), "google_cloud_asset_folder_feed": resourceCloudAssetFolderFeed(), "google_cloud_asset_organization_feed": resourceCloudAssetOrganizationFeed(), diff --git a/google-beta/resource_certificate_manager_certificate_map.go b/google-beta/resource_certificate_manager_certificate_map.go new file mode 100644 index 0000000000..e8900852f3 --- /dev/null +++ b/google-beta/resource_certificate_manager_certificate_map.go @@ -0,0 +1,478 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceCertificateManagerCertificateMap() *schema.Resource { + return &schema.Resource{ + Create: resourceCertificateManagerCertificateMapCreate, + Read: resourceCertificateManagerCertificateMapRead, + Update: resourceCertificateManagerCertificateMapUpdate, + Delete: resourceCertificateManagerCertificateMapDelete, + + Importer: &schema.ResourceImporter{ + State: resourceCertificateManagerCertificateMapImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `A user-defined name of the Certificate Map. Certificate Map names must be unique +globally and match the pattern 'projects/*/locations/*/certificateMaps/*'.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `One or more paragraphs of text description of a certificate map entry.`, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + Description: `Set of labels associated with a Certificate Map resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Creation timestamp of a Certificate Map. Timestamp is in RFC3339 UTC "Zulu" format, +accurate to nanoseconds with up to nine fractional digits. +Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".`, + }, + "gclb_targets": { + Type: schema.TypeList, + Computed: true, + Description: `A list of target proxies that use this Certificate Map`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_configs": { + Type: schema.TypeList, + Optional: true, + Description: `An IP configuration where this Certificate Map is serving`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_address": { + Type: schema.TypeString, + Optional: true, + Description: `An external IP address`, + }, + "ports": { + Type: schema.TypeList, + Optional: true, + Description: `A list of ports`, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + "target_https_proxy": { + Type: schema.TypeString, + Optional: true, + Description: `Proxy name must be in the format projects/*/locations/*/targetHttpsProxies/*. +This field is part of a union field 'target_proxy': Only one of 'targetHttpsProxy' or +'targetSslProxy' may be set.`, + }, + "target_ssl_proxy": { + Type: schema.TypeString, + Optional: true, + Description: `Proxy name must be in the format projects/*/locations/*/targetSslProxies/*. +This field is part of a union field 'target_proxy': Only one of 'targetHttpsProxy' or +'targetSslProxy' may be set.`, + }, + }, + }, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Update timestamp of a Certificate Map. Timestamp is in RFC3339 UTC "Zulu" format, +accurate to nanoseconds with up to nine fractional digits. +Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceCertificateManagerCertificateMapCreate(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 := expandCertificateManagerCertificateMapDescription(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 + } + labelsProp, err := expandCertificateManagerCertificateMapLabels(d.Get("labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := replaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps?certificateMapId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new CertificateMap: %#v", obj) + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMap: %s", err) + } + billingProject = project + + // 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 CertificateMap: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "projects/{{project}}/locations/global/certificateMaps/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = certificateManagerOperationWaitTime( + config, res, project, "Creating CertificateMap", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create CertificateMap: %s", err) + } + + log.Printf("[DEBUG] Finished creating CertificateMap %q: %#v", d.Id(), res) + + return resourceCertificateManagerCertificateMapRead(d, meta) +} + +func resourceCertificateManagerCertificateMapRead(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, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMap: %s", err) + } + billingProject = project + + // 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("CertificateManagerCertificateMap %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading CertificateMap: %s", err) + } + + if err := d.Set("description", flattenCertificateManagerCertificateMapDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMap: %s", err) + } + if err := d.Set("create_time", flattenCertificateManagerCertificateMapCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMap: %s", err) + } + if err := d.Set("update_time", flattenCertificateManagerCertificateMapUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMap: %s", err) + } + if err := d.Set("labels", flattenCertificateManagerCertificateMapLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMap: %s", err) + } + if err := d.Set("gclb_targets", flattenCertificateManagerCertificateMapGclbTargets(res["gclbTargets"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMap: %s", err) + } + + return nil +} + +func resourceCertificateManagerCertificateMapUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMap: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + descriptionProp, err := expandCertificateManagerCertificateMapDescription(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 + } + labelsProp, err := expandCertificateManagerCertificateMapLabels(d.Get("labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := replaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating CertificateMap %q: %#v", d.Id(), obj) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("labels") { + updateMask = append(updateMask, "labels") + } + // 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 CertificateMap %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating CertificateMap %q: %#v", d.Id(), res) + } + + err = certificateManagerOperationWaitTime( + config, res, project, "Updating CertificateMap", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + + return resourceCertificateManagerCertificateMapRead(d, meta) +} + +func resourceCertificateManagerCertificateMapDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMap: %s", err) + } + billingProject = project + + url, err := replaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting CertificateMap %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, "CertificateMap") + } + + err = certificateManagerOperationWaitTime( + config, res, project, "Deleting CertificateMap", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting CertificateMap %q: %#v", d.Id(), res) + return nil +} + +func resourceCertificateManagerCertificateMapImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/locations/global/certificateMaps/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "projects/{{project}}/locations/global/certificateMaps/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenCertificateManagerCertificateMapDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapCreateTime(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapUpdateTime(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapLabels(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapGclbTargets(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{}{ + "ip_configs": flattenCertificateManagerCertificateMapGclbTargetsIpConfigs(original["ipConfigs"], d, config), + "target_https_proxy": flattenCertificateManagerCertificateMapGclbTargetsTargetHttpsProxy(original["targetHttpsProxy"], d, config), + "target_ssl_proxy": flattenCertificateManagerCertificateMapGclbTargetsTargetSslProxy(original["targetSslProxy"], d, config), + }) + } + return transformed +} +func flattenCertificateManagerCertificateMapGclbTargetsIpConfigs(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{}{ + "ip_address": flattenCertificateManagerCertificateMapGclbTargetsIpConfigsIpAddress(original["ipAddress"], d, config), + "ports": flattenCertificateManagerCertificateMapGclbTargetsIpConfigsPorts(original["ports"], d, config), + }) + } + return transformed +} +func flattenCertificateManagerCertificateMapGclbTargetsIpConfigsIpAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapGclbTargetsIpConfigsPorts(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapGclbTargetsTargetHttpsProxy(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapGclbTargetsTargetSslProxy(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func expandCertificateManagerCertificateMapDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandCertificateManagerCertificateMapLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} diff --git a/google-beta/resource_certificate_manager_certificate_map_entry.go b/google-beta/resource_certificate_manager_certificate_map_entry.go new file mode 100644 index 0000000000..64cc097c8f --- /dev/null +++ b/google-beta/resource_certificate_manager_certificate_map_entry.go @@ -0,0 +1,531 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceCertificateManagerCertificateMapEntry() *schema.Resource { + return &schema.Resource{ + Create: resourceCertificateManagerCertificateMapEntryCreate, + Read: resourceCertificateManagerCertificateMapEntryRead, + Update: resourceCertificateManagerCertificateMapEntryUpdate, + Delete: resourceCertificateManagerCertificateMapEntryDelete, + + Importer: &schema.ResourceImporter{ + State: resourceCertificateManagerCertificateMapEntryImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "certificates": { + Type: schema.TypeList, + Required: true, + DiffSuppressFunc: projectNumberDiffSuppress, + Description: `A set of Certificates defines for the given hostname. +There can be defined up to fifteen certificates in each Certificate Map Entry. +Each certificate must match pattern projects/*/locations/*/certificates/*.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "map": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `A map entry that is inputted into the cetrificate map`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `A user-defined name of the Certificate Map Entry. Certificate Map Entry +names must be unique globally and match pattern +'projects/*/locations/*/certificateMaps/*/certificateMapEntries/*'`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `CertificateMapEntry is a list of certificate configurations, +that have been issued for a particular hostname`, + }, + "hostname": { + Type: schema.TypeString, + Optional: true, + Description: `A Hostname (FQDN, e.g. example.com) or a wildcard hostname expression (*.example.com) +for a set of hostnames with common suffix. Used as Server Name Indication (SNI) for +selecting a proper certificate.`, + ExactlyOneOf: []string{"hostname", "matcher"}, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + Description: `Set of labels associated with a Certificate Map Entry. +An object containing a list of "key": value pairs. +Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "matcher": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateEnum([]string{"MATCHER_UNSPECIFIED", "PRIMARY", ""}), + Description: `A predefined matcher for particular cases, other than SNI selection Possible values: ["MATCHER_UNSPECIFIED", "PRIMARY"]`, + ExactlyOneOf: []string{"hostname", "matcher"}, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Creation timestamp of a Certificate Map Entry. 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".`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `A serving state of this Certificate Map Entry. + +The status is undefined. + +The configuration is serving. + +Update is in progress. Some frontends may serve this configuration.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Update timestamp of a Certificate Map Entry. 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".`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceCertificateManagerCertificateMapEntryCreate(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 := expandCertificateManagerCertificateMapEntryDescription(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 + } + labelsProp, err := expandCertificateManagerCertificateMapEntryLabels(d.Get("labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + certificatesProp, err := expandCertificateManagerCertificateMapEntryCertificates(d.Get("certificates"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("certificates"); !isEmptyValue(reflect.ValueOf(certificatesProp)) && (ok || !reflect.DeepEqual(v, certificatesProp)) { + obj["certificates"] = certificatesProp + } + hostnameProp, err := expandCertificateManagerCertificateMapEntryHostname(d.Get("hostname"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("hostname"); !isEmptyValue(reflect.ValueOf(hostnameProp)) && (ok || !reflect.DeepEqual(v, hostnameProp)) { + obj["hostname"] = hostnameProp + } + matcherProp, err := expandCertificateManagerCertificateMapEntryMatcher(d.Get("matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("matcher"); !isEmptyValue(reflect.ValueOf(matcherProp)) && (ok || !reflect.DeepEqual(v, matcherProp)) { + obj["matcher"] = matcherProp + } + nameProp, err := expandCertificateManagerCertificateMapEntryName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + + url, err := replaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries?certificateMapEntryId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new CertificateMapEntry: %#v", obj) + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMapEntry: %s", err) + } + billingProject = project + + // 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 CertificateMapEntry: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = certificateManagerOperationWaitTime( + config, res, project, "Creating CertificateMapEntry", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create CertificateMapEntry: %s", err) + } + + log.Printf("[DEBUG] Finished creating CertificateMapEntry %q: %#v", d.Id(), res) + + return resourceCertificateManagerCertificateMapEntryRead(d, meta) +} + +func resourceCertificateManagerCertificateMapEntryRead(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, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMapEntry: %s", err) + } + billingProject = project + + // 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("CertificateManagerCertificateMapEntry %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + + if err := d.Set("description", flattenCertificateManagerCertificateMapEntryDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("create_time", flattenCertificateManagerCertificateMapEntryCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("update_time", flattenCertificateManagerCertificateMapEntryUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("labels", flattenCertificateManagerCertificateMapEntryLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("certificates", flattenCertificateManagerCertificateMapEntryCertificates(res["certificates"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("state", flattenCertificateManagerCertificateMapEntryState(res["state"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("hostname", flattenCertificateManagerCertificateMapEntryHostname(res["hostname"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("matcher", flattenCertificateManagerCertificateMapEntryMatcher(res["matcher"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + if err := d.Set("name", flattenCertificateManagerCertificateMapEntryName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading CertificateMapEntry: %s", err) + } + + return nil +} + +func resourceCertificateManagerCertificateMapEntryUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMapEntry: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + descriptionProp, err := expandCertificateManagerCertificateMapEntryDescription(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 + } + labelsProp, err := expandCertificateManagerCertificateMapEntryLabels(d.Get("labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + certificatesProp, err := expandCertificateManagerCertificateMapEntryCertificates(d.Get("certificates"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("certificates"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, certificatesProp)) { + obj["certificates"] = certificatesProp + } + hostnameProp, err := expandCertificateManagerCertificateMapEntryHostname(d.Get("hostname"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("hostname"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, hostnameProp)) { + obj["hostname"] = hostnameProp + } + matcherProp, err := expandCertificateManagerCertificateMapEntryMatcher(d.Get("matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("matcher"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, matcherProp)) { + obj["matcher"] = matcherProp + } + + url, err := replaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating CertificateMapEntry %q: %#v", d.Id(), obj) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("labels") { + updateMask = append(updateMask, "labels") + } + + if d.HasChange("certificates") { + updateMask = append(updateMask, "certificates") + } + + if d.HasChange("hostname") { + updateMask = append(updateMask, "hostname") + } + + if d.HasChange("matcher") { + updateMask = append(updateMask, "matcher") + } + // 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 CertificateMapEntry %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating CertificateMapEntry %q: %#v", d.Id(), res) + } + + err = certificateManagerOperationWaitTime( + config, res, project, "Updating CertificateMapEntry", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + + return resourceCertificateManagerCertificateMapEntryRead(d, meta) +} + +func resourceCertificateManagerCertificateMapEntryDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for CertificateMapEntry: %s", err) + } + billingProject = project + + url, err := replaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting CertificateMapEntry %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, "CertificateMapEntry") + } + + err = certificateManagerOperationWaitTime( + config, res, project, "Deleting CertificateMapEntry", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting CertificateMapEntry %q: %#v", d.Id(), res) + return nil +} + +func resourceCertificateManagerCertificateMapEntryImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/locations/global/certificateMaps/(?P[^/]+)/certificateMapEntries/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenCertificateManagerCertificateMapEntryDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryCreateTime(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryUpdateTime(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryLabels(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryCertificates(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryState(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryHostname(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryMatcher(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenCertificateManagerCertificateMapEntryName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + return NameFromSelfLinkStateFunc(v) +} + +func expandCertificateManagerCertificateMapEntryDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandCertificateManagerCertificateMapEntryLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} + +func expandCertificateManagerCertificateMapEntryCertificates(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandCertificateManagerCertificateMapEntryHostname(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandCertificateManagerCertificateMapEntryMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandCertificateManagerCertificateMapEntryName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return GetResourceNameFromSelfLink(v.(string)), nil +} diff --git a/google-beta/resource_certificate_manager_certificate_map_entry_generated_test.go b/google-beta/resource_certificate_manager_certificate_map_entry_generated_test.go new file mode 100644 index 0000000000..bbeed5fa64 --- /dev/null +++ b/google-beta/resource_certificate_manager_certificate_map_entry_generated_test.go @@ -0,0 +1,136 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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 TestAccCertificateManagerCertificateMapEntry_certificateManagerCertificateMapEntryFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCertificateManagerCertificateMapEntryDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCertificateManagerCertificateMapEntry_certificateManagerCertificateMapEntryFullExample(context), + }, + { + ResourceName: "google_certificate_manager_certificate_map_entry.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"map"}, + }, + }, + }) +} + +func testAccCertificateManagerCertificateMapEntry_certificateManagerCertificateMapEntryFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_certificate_manager_certificate_map" "certificate_map" { + name = "tf-test-cert-map-entry%{random_suffix}" + description = "My acceptance test certificate map" + labels = { + "terraform" : true, + "acc-test" : true, + } +} + +resource "google_certificate_manager_certificate_map_entry" "default" { + name = "tf-test-cert-map-entry%{random_suffix}" + description = "My acceptance test certificate map entry" + map = google_certificate_manager_certificate_map.certificate_map.name + labels = { + "terraform" : true, + "acc-test" : true, + } + certificates = [google_certificate_manager_certificate.certificate.id] + matcher = "PRIMARY" +} + +resource "google_certificate_manager_certificate" "certificate" { + name = "tf-test-cert-map-entry%{random_suffix}" + description = "The default cert" + scope = "DEFAULT" + managed { + domains = [ + google_certificate_manager_dns_authorization.instance.domain, + google_certificate_manager_dns_authorization.instance2.domain, + ] + dns_authorizations = [ + google_certificate_manager_dns_authorization.instance.id, + google_certificate_manager_dns_authorization.instance2.id, + ] + } +} + + +resource "google_certificate_manager_dns_authorization" "instance" { + name = "tf-test-dns-auth%{random_suffix}" + description = "The default dnss" + domain = "subdomain%{random_suffix}.hashicorptest.com" +} + +resource "google_certificate_manager_dns_authorization" "instance2" { + name = "tf-test-dns-auth2%{random_suffix}" + description = "The default dnss" + domain = "subdomain2%{random_suffix}.hashicorptest.com" +} +`, context) +} + +func testAccCheckCertificateManagerCertificateMapEntryDestroyProducer(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_certificate_manager_certificate_map_entry" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + url, err := replaceVarsForTest(config, rs, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = sendRequest(config, "GET", billingProject, url, config.userAgent, nil) + if err == nil { + return fmt.Errorf("CertificateManagerCertificateMapEntry still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/resource_certificate_manager_certificate_map_entry_sweeper_test.go b/google-beta/resource_certificate_manager_certificate_map_entry_sweeper_test.go new file mode 100644 index 0000000000..4509c31680 --- /dev/null +++ b/google-beta/resource_certificate_manager_certificate_map_entry_sweeper_test.go @@ -0,0 +1,124 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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("CertificateManagerCertificateMapEntry", &resource.Sweeper{ + Name: "CertificateManagerCertificateMapEntry", + F: testSweepCertificateManagerCertificateMapEntry, + }) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepCertificateManagerCertificateMapEntry(region string) error { + resourceName := "CertificateManagerCertificateMapEntry" + 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://certificatemanager.googleapis.com/v1/projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries", "?")[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["certificateMapEntries"] + 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://certificatemanager.googleapis.com/v1/projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{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-beta/resource_certificate_manager_certificate_map_generated_test.go b/google-beta/resource_certificate_manager_certificate_map_generated_test.go new file mode 100644 index 0000000000..87b51a2874 --- /dev/null +++ b/google-beta/resource_certificate_manager_certificate_map_generated_test.go @@ -0,0 +1,95 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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 TestAccCertificateManagerCertificateMap_certificateManagerCertificateMapBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCertificateManagerCertificateMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCertificateManagerCertificateMap_certificateManagerCertificateMapBasicExample(context), + }, + { + ResourceName: "google_certificate_manager_certificate_map.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name"}, + }, + }, + }) +} + +func testAccCertificateManagerCertificateMap_certificateManagerCertificateMapBasicExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_certificate_manager_certificate_map" "default" { + name = "tf-test-cert-map%{random_suffix}" + description = "My acceptance test certificate map" + labels = { + "terraform" : true, + "acc-test" : true, + } +} +`, context) +} + +func testAccCheckCertificateManagerCertificateMapDestroyProducer(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_certificate_manager_certificate_map" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + url, err := replaceVarsForTest(config, rs, "{{CertificateManagerBasePath}}projects/{{project}}/locations/global/certificateMaps/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = sendRequest(config, "GET", billingProject, url, config.userAgent, nil) + if err == nil { + return fmt.Errorf("CertificateManagerCertificateMap still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/resource_certificate_manager_certificate_map_sweeper_test.go b/google-beta/resource_certificate_manager_certificate_map_sweeper_test.go new file mode 100644 index 0000000000..8bd98a1897 --- /dev/null +++ b/google-beta/resource_certificate_manager_certificate_map_sweeper_test.go @@ -0,0 +1,124 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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("CertificateManagerCertificateMap", &resource.Sweeper{ + Name: "CertificateManagerCertificateMap", + F: testSweepCertificateManagerCertificateMap, + }) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepCertificateManagerCertificateMap(region string) error { + resourceName := "CertificateManagerCertificateMap" + 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://certificatemanager.googleapis.com/v1/projects/{{project}}/locations/global/certificateMaps", "?")[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["certificateMaps"] + 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://certificatemanager.googleapis.com/v1/projects/{{project}}/locations/global/certificateMaps/{{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-beta/resource_document_ai_processor_default_version.go b/google-beta/resource_document_ai_processor_default_version.go index e24da7594a..e0ae811ff4 100644 --- a/google-beta/resource_document_ai_processor_default_version.go +++ b/google-beta/resource_document_ai_processor_default_version.go @@ -50,7 +50,7 @@ func resourceDocumentAIProcessorDefaultVersion() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - DiffSuppressFunc: projectNumberDiffSupress, + DiffSuppressFunc: projectNumberDiffSuppress, Description: `The version to set`, }, }, diff --git a/website/docs/r/certificate_manager_certificate_map.html.markdown b/website/docs/r/certificate_manager_certificate_map.html.markdown new file mode 100644 index 0000000000..6b4bbc957c --- /dev/null +++ b/website/docs/r/certificate_manager_certificate_map.html.markdown @@ -0,0 +1,151 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# 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: "Certificate manager" +layout: "google" +page_title: "Google: google_certificate_manager_certificate_map" +sidebar_current: "docs-google-certificate-manager-certificate-map" +description: |- + CertificateMap defines a collection of certificate configurations, + which are usable by any associated target proxies +--- + +# google\_certificate\_manager\_certificate\_map + +CertificateMap defines a collection of certificate configurations, +which are usable by any associated target proxies + + + +~> **Warning:** These resources require allow-listing to use, and are not openly available to all Cloud customers. Engage with your Cloud account team to discuss how to onboard. + + +## Example Usage - Certificate Manager Certificate Map Basic + + +```hcl +resource "google_certificate_manager_certificate_map" "default" { + name = "cert-map" + description = "My acceptance test certificate map" + labels = { + "terraform" : true, + "acc-test" : true, + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `name` - + (Required) + A user-defined name of the Certificate Map. Certificate Map names must be unique + globally and match the pattern `projects/*/locations/*/certificateMaps/*`. + + +- - - + + +* `description` - + (Optional) + One or more paragraphs of text description of a certificate map entry. + +* `labels` - + (Optional) + Set of labels associated with a Certificate Map resource. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/global/certificateMaps/{{name}}` + +* `create_time` - + Creation timestamp of a Certificate Map. Timestamp is in RFC3339 UTC "Zulu" format, + accurate to nanoseconds with up to nine fractional digits. + Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + +* `update_time` - + Update timestamp of a Certificate Map. Timestamp is in RFC3339 UTC "Zulu" format, + accurate to nanoseconds with up to nine fractional digits. + Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + +* `gclb_targets` - + A list of target proxies that use this Certificate Map + Structure is [documented below](#nested_gclb_targets). + + +The `gclb_targets` block contains: + +* `ip_configs` - + (Optional) + An IP configuration where this Certificate Map is serving + Structure is [documented below](#nested_ip_configs). + +* `target_https_proxy` - + (Optional) + Proxy name must be in the format projects/*/locations/*/targetHttpsProxies/*. + This field is part of a union field `target_proxy`: Only one of `targetHttpsProxy` or + `targetSslProxy` may be set. + +* `target_ssl_proxy` - + (Optional) + Proxy name must be in the format projects/*/locations/*/targetSslProxies/*. + This field is part of a union field `target_proxy`: Only one of `targetHttpsProxy` or + `targetSslProxy` may be set. + + +The `ip_configs` block supports: + +* `ip_address` - + (Optional) + An external IP address + +* `ports` - + (Optional) + A list of ports + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + + +CertificateMap can be imported using any of these accepted formats: + +``` +$ terraform import google_certificate_manager_certificate_map.default projects/{{project}}/locations/global/certificateMaps/{{name}} +$ terraform import google_certificate_manager_certificate_map.default {{project}}/{{name}} +$ terraform import google_certificate_manager_certificate_map.default {{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#user_project_override). diff --git a/website/docs/r/certificate_manager_certificate_map_entry.html.markdown b/website/docs/r/certificate_manager_certificate_map_entry.html.markdown new file mode 100644 index 0000000000..ae7a2e9e72 --- /dev/null +++ b/website/docs/r/certificate_manager_certificate_map_entry.html.markdown @@ -0,0 +1,189 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# 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: "Certificate manager" +layout: "google" +page_title: "Google: google_certificate_manager_certificate_map_entry" +sidebar_current: "docs-google-certificate-manager-certificate-map-entry" +description: |- + CertificateMapEntry is a list of certificate configurations, + that have been issued for a particular hostname +--- + +# google\_certificate\_manager\_certificate\_map\_entry + +CertificateMapEntry is a list of certificate configurations, +that have been issued for a particular hostname + + + +~> **Warning:** These resources require allow-listing to use, and are not openly available to all Cloud customers. Engage with your Cloud account team to discuss how to onboard. + + +## Example Usage - Certificate Manager Certificate Map Entry Full + + +```hcl +resource "google_certificate_manager_certificate_map" "certificate_map" { + name = "cert-map-entry" + description = "My acceptance test certificate map" + labels = { + "terraform" : true, + "acc-test" : true, + } +} + +resource "google_certificate_manager_certificate_map_entry" "default" { + name = "cert-map-entry" + description = "My acceptance test certificate map entry" + map = google_certificate_manager_certificate_map.certificate_map.name + labels = { + "terraform" : true, + "acc-test" : true, + } + certificates = [google_certificate_manager_certificate.certificate.id] + matcher = "PRIMARY" +} + +resource "google_certificate_manager_certificate" "certificate" { + name = "cert-map-entry" + description = "The default cert" + scope = "DEFAULT" + managed { + domains = [ + google_certificate_manager_dns_authorization.instance.domain, + google_certificate_manager_dns_authorization.instance2.domain, + ] + dns_authorizations = [ + google_certificate_manager_dns_authorization.instance.id, + google_certificate_manager_dns_authorization.instance2.id, + ] + } +} + + +resource "google_certificate_manager_dns_authorization" "instance" { + name = "dns-auth" + description = "The default dnss" + domain = "subdomain.hashicorptest.com" +} + +resource "google_certificate_manager_dns_authorization" "instance2" { + name = "dns-auth2" + description = "The default dnss" + domain = "subdomain2.hashicorptest.com" +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `certificates` - + (Required) + A set of Certificates defines for the given hostname. + There can be defined up to fifteen certificates in each Certificate Map Entry. + Each certificate must match pattern projects/*/locations/*/certificates/*. + +* `name` - + (Required) + A user-defined name of the Certificate Map Entry. Certificate Map Entry + names must be unique globally and match pattern + 'projects/*/locations/*/certificateMaps/*/certificateMapEntries/*' + +* `map` - + (Required) + A map entry that is inputted into the cetrificate map + + +- - - + + +* `description` - + (Optional) + CertificateMapEntry is a list of certificate configurations, + that have been issued for a particular hostname + +* `labels` - + (Optional) + Set of labels associated with a Certificate Map Entry. + An object containing a list of "key": value pairs. + Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. + +* `hostname` - + (Optional) + A Hostname (FQDN, e.g. example.com) or a wildcard hostname expression (*.example.com) + for a set of hostnames with common suffix. Used as Server Name Indication (SNI) for + selecting a proper certificate. + +* `matcher` - + (Optional) + A predefined matcher for particular cases, other than SNI selection + Possible values are `MATCHER_UNSPECIFIED` and `PRIMARY`. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}}` + +* `create_time` - + Creation timestamp of a Certificate Map Entry. 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". + +* `update_time` - + Update timestamp of a Certificate Map Entry. 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". + +* `state` - + A serving state of this Certificate Map Entry. + The status is undefined. + The configuration is serving. + Update is in progress. Some frontends may serve this configuration. + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + + +CertificateMapEntry can be imported using any of these accepted formats: + +``` +$ terraform import google_certificate_manager_certificate_map_entry.default projects/{{project}}/locations/global/certificateMaps/{{map}}/certificateMapEntries/{{name}} +$ terraform import google_certificate_manager_certificate_map_entry.default {{project}}/{{map}}/{{name}} +$ terraform import google_certificate_manager_certificate_map_entry.default {{map}}/{{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#user_project_override). diff --git a/website/google.erb b/website/google.erb index ad0e5591db..aae84a7229 100644 --- a/website/google.erb +++ b/website/google.erb @@ -521,6 +521,14 @@ google_certificate_manager_certificate +
  • + google_certificate_manager_certificate_map +
  • + +
  • + google_certificate_manager_certificate_map_entry +
  • +
  • google_certificate_manager_dns_authorization