blob: 1592cf25ac2cfe28ac4d8387c786c4a48d0a94de [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
// ----------------------------------------------------------------------------
//
// *** 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 cloudrun
import (
"context"
"fmt"
"log"
"reflect"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/verify"
)
func hasMetadata(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error {
newCount := diff.Get("metadata.#")
if newCount.(int) < 1 {
return fmt.Errorf("Insufficient \"metadata\" blocks. 1 \"metadata\" block is required.")
}
return nil
}
func ResourceCloudRunDomainMapping() *schema.Resource {
return &schema.Resource{
Create: resourceCloudRunDomainMappingCreate,
Read: resourceCloudRunDomainMappingRead,
Delete: resourceCloudRunDomainMappingDelete,
Importer: &schema.ResourceImporter{
State: resourceCloudRunDomainMappingImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(20 * time.Minute),
Delete: schema.DefaultTimeout(20 * time.Minute),
},
SchemaVersion: 1,
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceCloudRunDomainMappingResourceV0().CoreConfigSchema().ImpliedType(),
Upgrade: ResourceCloudRunDomainMappingUpgradeV0,
Version: 0,
},
},
CustomizeDiff: customdiff.All(
hasMetadata,
tpgresource.SetMetadataLabelsDiff,
tpgresource.SetMetadataAnnotationsDiff,
tpgresource.DefaultProviderProject,
),
Schema: map[string]*schema.Schema{
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `The location of the cloud run instance. eg us-central1`,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Name should be a [verified](https://support.google.com/webmasters/answer/9008080) domain`,
},
"spec": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
Description: `The spec for this DomainMapping.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"route_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
Description: `The name of the Cloud Run Service that this DomainMapping applies to.
The route must exist.`,
},
"certificate_mode": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: verify.ValidateEnum([]string{"NONE", "AUTOMATIC", ""}),
Description: `The mode of the certificate. Default value: "AUTOMATIC" Possible values: ["NONE", "AUTOMATIC"]`,
Default: "AUTOMATIC",
},
"force_override": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Description: `If set, the mapping will override any mapping set before this spec was set.
It is recommended that the user leaves this empty to receive an error
warning about a potential conflict and only set it once the respective UI
has given such a warning.`,
},
},
},
},
"metadata": {
Type: schema.TypeList,
Computed: true,
Optional: true,
ForceNew: true,
Description: `Metadata associated with this DomainMapping.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"namespace": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `In Cloud Run the namespace must be equal to either the
project ID or project number.`,
},
"annotations": {
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
Description: `Annotations is a key value map stored with a resource that
may be set by external tools to store and retrieve arbitrary metadata. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations
**Note**: The Cloud Run API may add additional annotations that were not provided in your config.
If terraform plan shows a diff where a server-side annotation is added, you can add it to your config
or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field.
**Note**: This field is non-authoritative, and will only manage the annotations present in your configuration.
Please refer to the field 'effective_annotations' for all of the annotations present on the resource.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"labels": {
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
Description: `Map of string keys and values that can be used to organize and categorize
(scope and select) objects. May match selectors of replication controllers
and routes.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
Please refer to the field 'effective_labels' for all of the labels present on the resource.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"effective_annotations": {
Type: schema.TypeMap,
Computed: true,
ForceNew: true,
Description: `All of annotations (key/value pairs) present on the resource in GCP, including the annotations configured through Terraform, other clients and services.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"effective_labels": {
Type: schema.TypeMap,
Computed: true,
ForceNew: true,
Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"generation": {
Type: schema.TypeInt,
Computed: true,
Description: `A sequence number representing a specific generation of the desired state.`,
},
"resource_version": {
Type: schema.TypeString,
Computed: true,
Description: `An opaque value that represents the internal version of this object that
can be used by clients to determine when objects have changed. May be used
for optimistic concurrency, change detection, and the watch operation on a
resource or set of resources. They may only be valid for a
particular resource or set of resources.
More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency`,
},
"self_link": {
Type: schema.TypeString,
Computed: true,
Description: `SelfLink is a URL representing this object.`,
},
"terraform_labels": {
Type: schema.TypeMap,
Computed: true,
ForceNew: true,
Description: `The combination of labels configured directly on the resource
and default labels configured on the provider.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"uid": {
Type: schema.TypeString,
Computed: true,
Description: `UID is a unique id generated by the server on successful creation of a resource and is not
allowed to change on PUT operations.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids`,
},
},
},
},
"status": {
Type: schema.TypeList,
Computed: true,
Description: `The current status of the DomainMapping.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"resource_records": {
Type: schema.TypeList,
Optional: true,
Description: `The resource records required to configure this domain mapping. These
records must be added to the domain's DNS configuration in order to
serve the application via this domain mapping.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidateEnum([]string{"A", "AAAA", "CNAME", ""}),
Description: `Resource record type. Example: 'AAAA'. Possible values: ["A", "AAAA", "CNAME"]`,
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: `Relative name of the object affected by this record. Only applicable for
'CNAME' records. Example: 'www'.`,
},
"rrdata": {
Type: schema.TypeString,
Computed: true,
Description: `Data for this record. Values vary by record type, as defined in RFC 1035
(section 5) and RFC 1034 (section 3.6.1).`,
},
},
},
},
"conditions": {
Type: schema.TypeList,
Computed: true,
Description: `Array of observed DomainMappingConditions, indicating the current state
of the DomainMapping.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"message": {
Type: schema.TypeString,
Computed: true,
Description: `Human readable message indicating details about the current status.`,
},
"reason": {
Type: schema.TypeString,
Computed: true,
Description: `One-word CamelCase reason for the condition's current status.`,
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: `Status of the condition, one of True, False, Unknown.`,
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: `Type of domain mapping condition.`,
},
},
},
},
"mapped_route_name": {
Type: schema.TypeString,
Computed: true,
Description: `The name of the route that the mapping currently points to.`,
},
"observed_generation": {
Type: schema.TypeInt,
Computed: true,
Description: `ObservedGeneration is the 'Generation' of the DomainMapping that
was last processed by the controller.`,
},
},
},
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
UseJSONNumber: true,
}
}
func resourceCloudRunDomainMappingCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}
obj := make(map[string]interface{})
specProp, err := expandCloudRunDomainMappingSpec(d.Get("spec"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("spec"); !tpgresource.IsEmptyValue(reflect.ValueOf(specProp)) && (ok || !reflect.DeepEqual(v, specProp)) {
obj["spec"] = specProp
}
metadataProp, err := expandCloudRunDomainMappingMetadata(d.Get("metadata"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("metadata"); !tpgresource.IsEmptyValue(reflect.ValueOf(metadataProp)) && (ok || !reflect.DeepEqual(v, metadataProp)) {
obj["metadata"] = metadataProp
}
obj, err = resourceCloudRunDomainMappingEncoder(d, meta, obj)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{CloudRunBasePath}}apis/domains.cloudrun.com/v1/namespaces/{{project}}/domainmappings")
if err != nil {
return err
}
log.Printf("[DEBUG] Creating new DomainMapping: %#v", obj)
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for DomainMapping: %s", err)
}
billingProject = project
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutCreate),
ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCloudRunCreationConflict},
})
if err != nil {
return fmt.Errorf("Error creating DomainMapping: %s", err)
}
// Store the ID now
id, err := tpgresource.ReplaceVars(d, config, "locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
err = transport_tpg.PollingWaitTime(resourceCloudRunDomainMappingPollRead(d, meta), PollCheckKnativeStatusFunc(res), "Creating DomainMapping", d.Timeout(schema.TimeoutCreate), 1)
if err != nil {
return fmt.Errorf("Error waiting to create DomainMapping: %s", err)
}
log.Printf("[DEBUG] Finished creating DomainMapping %q: %#v", d.Id(), res)
return resourceCloudRunDomainMappingRead(d, meta)
}
func resourceCloudRunDomainMappingPollRead(d *schema.ResourceData, meta interface{}) transport_tpg.PollReadFunc {
return func() (map[string]interface{}, error) {
config := meta.(*transport_tpg.Config)
url, err := tpgresource.ReplaceVars(d, config, "{{CloudRunBasePath}}apis/domains.cloudrun.com/v1/namespaces/{{project}}/domainmappings/{{name}}")
if err != nil {
return nil, err
}
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return nil, fmt.Errorf("Error fetching project for DomainMapping: %s", err)
}
billingProject = project
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return nil, err
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "GET",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCloudRunCreationConflict},
})
if err != nil {
return res, err
}
res, err = resourceCloudRunDomainMappingDecoder(d, meta, res)
if err != nil {
return nil, err
}
if res == nil {
return nil, tpgresource.Fake404("decoded", "CloudRunDomainMapping")
}
return res, nil
}
}
func resourceCloudRunDomainMappingRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{CloudRunBasePath}}apis/domains.cloudrun.com/v1/namespaces/{{project}}/domainmappings/{{name}}")
if err != nil {
return err
}
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for DomainMapping: %s", err)
}
billingProject = project
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "GET",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCloudRunCreationConflict},
})
if err != nil {
return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudRunDomainMapping %q", d.Id()))
}
res, err = resourceCloudRunDomainMappingDecoder(d, meta, res)
if err != nil {
return err
}
if res == nil {
// Decoding the object has resulted in it being gone. It may be marked deleted
log.Printf("[DEBUG] Removing CloudRunDomainMapping because it no longer exists.")
d.SetId("")
return nil
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading DomainMapping: %s", err)
}
if err := d.Set("status", flattenCloudRunDomainMappingStatus(res["status"], d, config)); err != nil {
return fmt.Errorf("Error reading DomainMapping: %s", err)
}
if err := d.Set("spec", flattenCloudRunDomainMappingSpec(res["spec"], d, config)); err != nil {
return fmt.Errorf("Error reading DomainMapping: %s", err)
}
if err := d.Set("metadata", flattenCloudRunDomainMappingMetadata(res["metadata"], d, config)); err != nil {
return fmt.Errorf("Error reading DomainMapping: %s", err)
}
return nil
}
func resourceCloudRunDomainMappingDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for DomainMapping: %s", err)
}
billingProject = project
url, err := tpgresource.ReplaceVars(d, config, "{{CloudRunBasePath}}apis/domains.cloudrun.com/v1/namespaces/{{project}}/domainmappings/{{name}}")
if err != nil {
return err
}
var obj map[string]interface{}
log.Printf("[DEBUG] Deleting DomainMapping %q", d.Id())
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "DELETE",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutDelete),
ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsCloudRunCreationConflict},
})
if err != nil {
return transport_tpg.HandleNotFoundError(err, d, "DomainMapping")
}
log.Printf("[DEBUG] Finished deleting DomainMapping %q: %#v", d.Id(), res)
return nil
}
func resourceCloudRunDomainMappingImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*transport_tpg.Config)
if err := tpgresource.ParseImportId([]string{
"^locations/(?P<location>[^/]+)/namespaces/(?P<project>[^/]+)/domainmappings/(?P<name>[^/]+)$",
"^(?P<location>[^/]+)/(?P<project>[^/]+)/(?P<name>[^/]+)$",
"^(?P<location>[^/]+)/(?P<name>[^/]+)$",
}, d, config); err != nil {
return nil, err
}
// Replace import id for the resource id
id, err := tpgresource.ReplaceVars(d, config, "locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenCloudRunDomainMappingStatus(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["conditions"] =
flattenCloudRunDomainMappingStatusConditions(original["conditions"], d, config)
transformed["observed_generation"] =
flattenCloudRunDomainMappingStatusObservedGeneration(original["observedGeneration"], d, config)
transformed["resource_records"] =
flattenCloudRunDomainMappingStatusResourceRecords(original["resourceRecords"], d, config)
transformed["mapped_route_name"] =
flattenCloudRunDomainMappingStatusMappedRouteName(original["mappedRouteName"], d, config)
return []interface{}{transformed}
}
func flattenCloudRunDomainMappingStatusConditions(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"message": flattenCloudRunDomainMappingStatusConditionsMessage(original["message"], d, config),
"status": flattenCloudRunDomainMappingStatusConditionsStatus(original["status"], d, config),
"reason": flattenCloudRunDomainMappingStatusConditionsReason(original["reason"], d, config),
"type": flattenCloudRunDomainMappingStatusConditionsType(original["type"], d, config),
})
}
return transformed
}
func flattenCloudRunDomainMappingStatusConditionsMessage(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingStatusConditionsStatus(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingStatusConditionsReason(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingStatusConditionsType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingStatusObservedGeneration(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := tpgresource.StringToFixed64(strVal); 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 flattenCloudRunDomainMappingStatusResourceRecords(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"type": flattenCloudRunDomainMappingStatusResourceRecordsType(original["type"], d, config),
"rrdata": flattenCloudRunDomainMappingStatusResourceRecordsRrdata(original["rrdata"], d, config),
"name": flattenCloudRunDomainMappingStatusResourceRecordsName(original["name"], d, config),
})
}
return transformed
}
func flattenCloudRunDomainMappingStatusResourceRecordsType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingStatusResourceRecordsRrdata(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingStatusResourceRecordsName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingStatusMappedRouteName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingSpec(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["force_override"] =
flattenCloudRunDomainMappingSpecForceOverride(original["forceOverride"], d, config)
transformed["route_name"] =
flattenCloudRunDomainMappingSpecRouteName(original["routeName"], d, config)
transformed["certificate_mode"] =
flattenCloudRunDomainMappingSpecCertificateMode(original["certificateMode"], d, config)
return []interface{}{transformed}
}
func flattenCloudRunDomainMappingSpecForceOverride(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// We want to ignore read on this field, but cannot because it is nested
return d.Get("spec.0.force_override")
}
func flattenCloudRunDomainMappingSpecRouteName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingSpecCertificateMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingMetadata(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["labels"] =
flattenCloudRunDomainMappingMetadataLabels(original["labels"], d, config)
transformed["generation"] =
flattenCloudRunDomainMappingMetadataGeneration(original["generation"], d, config)
transformed["resource_version"] =
flattenCloudRunDomainMappingMetadataResourceVersion(original["resourceVersion"], d, config)
transformed["self_link"] =
flattenCloudRunDomainMappingMetadataSelfLink(original["selfLink"], d, config)
transformed["uid"] =
flattenCloudRunDomainMappingMetadataUid(original["uid"], d, config)
transformed["namespace"] =
flattenCloudRunDomainMappingMetadataNamespace(original["namespace"], d, config)
transformed["annotations"] =
flattenCloudRunDomainMappingMetadataAnnotations(original["annotations"], d, config)
transformed["terraform_labels"] =
flattenCloudRunDomainMappingMetadataTerraformLabels(original["labels"], d, config)
transformed["effective_labels"] =
flattenCloudRunDomainMappingMetadataEffectiveLabels(original["labels"], d, config)
transformed["effective_annotations"] =
flattenCloudRunDomainMappingMetadataEffectiveAnnotations(original["annotations"], d, config)
return []interface{}{transformed}
}
func flattenCloudRunDomainMappingMetadataLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
transformed := make(map[string]interface{})
if l, ok := d.GetOkExists("metadata.0.labels"); ok {
for k := range l.(map[string]interface{}) {
transformed[k] = v.(map[string]interface{})[k]
}
}
return transformed
}
func flattenCloudRunDomainMappingMetadataGeneration(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := tpgresource.StringToFixed64(strVal); 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 flattenCloudRunDomainMappingMetadataResourceVersion(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingMetadataSelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingMetadataUid(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingMetadataNamespace(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return d.Get("project")
}
func flattenCloudRunDomainMappingMetadataAnnotations(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
transformed := make(map[string]interface{})
if l, ok := d.GetOkExists("metadata.0.annotations"); ok {
for k := range l.(map[string]interface{}) {
transformed[k] = v.(map[string]interface{})[k]
}
}
return transformed
}
func flattenCloudRunDomainMappingMetadataTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
transformed := make(map[string]interface{})
if l, ok := d.GetOkExists("metadata.0.terraform_labels"); ok {
for k := range l.(map[string]interface{}) {
transformed[k] = v.(map[string]interface{})[k]
}
}
return transformed
}
func flattenCloudRunDomainMappingMetadataEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenCloudRunDomainMappingMetadataEffectiveAnnotations(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func expandCloudRunDomainMappingSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedForceOverride, err := expandCloudRunDomainMappingSpecForceOverride(original["force_override"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedForceOverride); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["forceOverride"] = transformedForceOverride
}
transformedRouteName, err := expandCloudRunDomainMappingSpecRouteName(original["route_name"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRouteName); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["routeName"] = transformedRouteName
}
transformedCertificateMode, err := expandCloudRunDomainMappingSpecCertificateMode(original["certificate_mode"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedCertificateMode); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["certificateMode"] = transformedCertificateMode
}
return transformed, nil
}
func expandCloudRunDomainMappingSpecForceOverride(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandCloudRunDomainMappingSpecRouteName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return tpgresource.GetResourceNameFromSelfLink(v.(string)), nil
}
func expandCloudRunDomainMappingSpecCertificateMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandCloudRunDomainMappingMetadata(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedGeneration, err := expandCloudRunDomainMappingMetadataGeneration(original["generation"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedGeneration); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["generation"] = transformedGeneration
}
transformedResourceVersion, err := expandCloudRunDomainMappingMetadataResourceVersion(original["resource_version"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedResourceVersion); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["resourceVersion"] = transformedResourceVersion
}
transformedSelfLink, err := expandCloudRunDomainMappingMetadataSelfLink(original["self_link"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedSelfLink); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["selfLink"] = transformedSelfLink
}
transformedUid, err := expandCloudRunDomainMappingMetadataUid(original["uid"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedUid); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["uid"] = transformedUid
}
transformedNamespace, err := expandCloudRunDomainMappingMetadataNamespace(original["namespace"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedNamespace); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["namespace"] = transformedNamespace
}
transformedEffectiveLabels, err := expandCloudRunDomainMappingMetadataEffectiveLabels(original["effective_labels"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEffectiveLabels); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["labels"] = transformedEffectiveLabels
}
transformedEffectiveAnnotations, err := expandCloudRunDomainMappingMetadataEffectiveAnnotations(original["effective_annotations"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEffectiveAnnotations); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["annotations"] = transformedEffectiveAnnotations
}
return transformed, nil
}
func expandCloudRunDomainMappingMetadataGeneration(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandCloudRunDomainMappingMetadataResourceVersion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandCloudRunDomainMappingMetadataSelfLink(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandCloudRunDomainMappingMetadataUid(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandCloudRunDomainMappingMetadataNamespace(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandCloudRunDomainMappingMetadataEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.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 expandCloudRunDomainMappingMetadataEffectiveAnnotations(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.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 resourceCloudRunDomainMappingEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) {
name := d.Get("name").(string)
metadata := obj["metadata"].(map[string]interface{})
metadata["name"] = name
// The only acceptable version/kind right now
obj["apiVersion"] = "domains.cloudrun.com/v1"
obj["kind"] = "DomainMapping"
return obj, nil
}
func resourceCloudRunDomainMappingDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) {
// metadata is not present if the API returns an error
if obj, ok := res["metadata"]; ok {
if meta, ok := obj.(map[string]interface{}); ok {
res["name"] = meta["name"]
} else {
return nil, fmt.Errorf("Unable to decode 'metadata' block from API response.")
}
}
return res, nil
}
var domainMappingGoogleProvidedLocationLabel = "cloud.googleapis.com/location"
var domainMappingGoogleProvidedOverrideLabel = "run.googleapis.com/overrideAt"
var domainMappingGoogleProvidedLabels = []string{
domainMappingGoogleProvidedLocationLabel,
domainMappingGoogleProvidedOverrideLabel,
}
func DomainMappingLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
// Suppress diffs for the labels provided by Google
for _, label := range domainMappingGoogleProvidedLabels {
if strings.Contains(k, label) && new == "" {
return true
}
}
// Let diff be determined by labels (above)
if strings.Contains(k, "labels.%") {
return true
}
// For other keys, don't suppress diff.
return false
}
func resourceCloudRunDomainMappingResourceV0() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `The location of the cloud run instance. eg us-central1`,
},
"metadata": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
Description: `Metadata associated with this DomainMapping.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"namespace": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `In Cloud Run the namespace must be equal to either the
project ID or project number.`,
},
"annotations": {
Type: schema.TypeMap,
Computed: true,
Optional: true,
ForceNew: true,
DiffSuppressFunc: cloudrunAnnotationDiffSuppress,
Description: `Annotations is a key value map stored with a resource that
may be set by external tools to store and retrieve arbitrary metadata. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations
**Note**: The Cloud Run API may add additional annotations that were not provided in your config.
If terraform plan shows a diff where a server-side annotation is added, you can add it to your config
or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"labels": {
Type: schema.TypeMap,
Computed: true,
Optional: true,
ForceNew: true,
DiffSuppressFunc: DomainMappingLabelDiffSuppress,
Description: `Map of string keys and values that can be used to organize and categorize
(scope and select) objects. May match selectors of replication controllers
and routes.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"generation": {
Type: schema.TypeInt,
Computed: true,
Description: `A sequence number representing a specific generation of the desired state.`,
},
"resource_version": {
Type: schema.TypeString,
Computed: true,
Description: `An opaque value that represents the internal version of this object that
can be used by clients to determine when objects have changed. May be used
for optimistic concurrency, change detection, and the watch operation on a
resource or set of resources. They may only be valid for a
particular resource or set of resources.
More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency`,
},
"self_link": {
Type: schema.TypeString,
Computed: true,
Description: `SelfLink is a URL representing this object.`,
},
"uid": {
Type: schema.TypeString,
Computed: true,
Description: `UID is a unique id generated by the server on successful creation of a resource and is not
allowed to change on PUT operations.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids`,
},
},
},
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Name should be a [verified](https://support.google.com/webmasters/answer/9008080) domain`,
},
"spec": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
Description: `The spec for this DomainMapping.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"route_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
Description: `The name of the Cloud Run Service that this DomainMapping applies to.
The route must exist.`,
},
"certificate_mode": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: verify.ValidateEnum([]string{"NONE", "AUTOMATIC", ""}),
Description: `The mode of the certificate. Default value: "AUTOMATIC" Possible values: ["NONE", "AUTOMATIC"]`,
Default: "AUTOMATIC",
},
"force_override": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Description: `If set, the mapping will override any mapping set before this spec was set.
It is recommended that the user leaves this empty to receive an error
warning about a potential conflict and only set it once the respective UI
has given such a warning.`,
},
},
},
},
"status": {
Type: schema.TypeList,
Computed: true,
Description: `The current status of the DomainMapping.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"resource_records": {
Type: schema.TypeList,
Optional: true,
Description: `The resource records required to configure this domain mapping. These
records must be added to the domain's DNS configuration in order to
serve the application via this domain mapping.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidateEnum([]string{"A", "AAAA", "CNAME", ""}),
Description: `Resource record type. Example: 'AAAA'. Possible values: ["A", "AAAA", "CNAME"]`,
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: `Relative name of the object affected by this record. Only applicable for
'CNAME' records. Example: 'www'.`,
},
"rrdata": {
Type: schema.TypeString,
Computed: true,
Description: `Data for this record. Values vary by record type, as defined in RFC 1035
(section 5) and RFC 1034 (section 3.6.1).`,
},
},
},
},
"conditions": {
Type: schema.TypeList,
Computed: true,
Description: `Array of observed DomainMappingConditions, indicating the current state
of the DomainMapping.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"message": {
Type: schema.TypeString,
Computed: true,
Description: `Human readable message indicating details about the current status.`,
},
"reason": {
Type: schema.TypeString,
Computed: true,
Description: `One-word CamelCase reason for the condition's current status.`,
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: `Status of the condition, one of True, False, Unknown.`,
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: `Type of domain mapping condition.`,
},
},
},
},
"mapped_route_name": {
Type: schema.TypeString,
Computed: true,
Description: `The name of the route that the mapping currently points to.`,
},
"observed_generation": {
Type: schema.TypeInt,
Computed: true,
Description: `ObservedGeneration is the 'Generation' of the DomainMapping that
was last processed by the controller.`,
},
},
},
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
UseJSONNumber: true,
}
}
func ResourceCloudRunDomainMappingUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
log.Printf("[DEBUG] Attributes before migration: %#v", rawState)
if rawState["metadata"] != nil {
rawMetadatas := rawState["metadata"].([]interface{})
if len(rawMetadatas) > 0 && rawMetadatas[0] != nil {
// Upgrade labels fields
rawMetadata := rawMetadatas[0].(map[string]interface{})
rawLabels := rawMetadata["labels"]
rawTerraformLabels := rawMetadata["terraform_labels"]
if rawLabels != nil {
labels := make(map[string]interface{})
effectiveLabels := make(map[string]interface{})
for k, v := range rawLabels.(map[string]interface{}) {
effectiveLabels[k] = v
if !strings.Contains(k, domainMappingGoogleProvidedLocationLabel) && !strings.Contains(k, domainMappingGoogleProvidedOverrideLabel) {
labels[k] = v
}
}
rawMetadata["labels"] = labels
rawMetadata["effective_labels"] = effectiveLabels
if rawTerraformLabels == nil {
rawMetadata["terraform_labels"] = labels
}
}
upgradeAnnotations(rawMetadata)
rawState["metadata"] = []interface{}{rawMetadata}
}
}
log.Printf("[DEBUG] Attributes after migration: %#v", rawState)
return rawState, nil
}