Merge branch 'master' into paddy_flow_logs

This commit is contained in:
Paddy 2018-05-02 11:47:43 -07:00
commit 325a118053
46 changed files with 2617 additions and 899 deletions

View File

@ -1,5 +1,7 @@
dist: trusty dist: trusty
sudo: false sudo: required
services:
- docker
language: go language: go
go: go:
- 1.9.1 - 1.9.1
@ -16,6 +18,7 @@ script:
- make test - make test
- make vendor-status - make vendor-status
- make vet - make vet
- make website-test
branches: branches:
only: only:

View File

@ -1,7 +1,30 @@
## 1.10.1 (Unreleased) ## 1.11.1 (Unreleased)
FEATURES:
* spanner: New resources to manage IAM for Spanner Databases: google_spanner_database_iam_binding, google_spanner_database_iam_member, and google_spanner_database_iam_policy [GH-1386]
IMPROVEMENTS: IMPROVEMENTS:
* compute: Add `public_ptr_domain_name` to `google_compute_instance`. [GH-1349] * compute: Autogenerate `google_vpn_gateway` [GH-1409]
## 1.11.0 (May 01, 2018)
IMPROVEMENTS:
* compute: Add `public_ptr_domain_name` to `google_compute_instance`. ([#1349](https://github.com/terraform-providers/terraform-provider-google/issues/1349))
* compute: Autogenerate `google_compute_global_address`. ([#1379](https://github.com/terraform-providers/terraform-provider-google/issues/1379))
* compute: Autogenerate `google_compute_target_http_proxy`. ([#1391](https://github.com/terraform-providers/terraform-provider-google/issues/1391))
* compute: Autogenerate `google_compute_target_http_proxy`. ([#1373](https://github.com/terraform-providers/terraform-provider-google/issues/1373))
* compute: Simplify autogenerated code for `google_compute_target_http_proxy` and `google_compute_target_ssl_proxy`. ([#1395](https://github.com/terraform-providers/terraform-provider-google/issues/1395))
* compute: Use partial state setting in `google_compute_target_http_proxy` and `google_compute_target_ssl_proxy` to better handle mid-update errors. ([#1392](https://github.com/terraform-providers/terraform-provider-google/issues/1392))
* compute: Use the v1 API for `google_compute_address` ([#1384](https://github.com/terraform-providers/terraform-provider-google/issues/1384))
* compute: Properly detect when `public_ptr_domain_name` isn't set. ([#1383](https://github.com/terraform-providers/terraform-provider-google/issues/1383))
* compute: Use the v1 API for `google_compute_ssl_policy` ([#1368](https://github.com/terraform-providers/terraform-provider-google/issues/1368))
* container: Add `issue_client_certificate` to `google_container_cluster`. ([#1396](https://github.com/terraform-providers/terraform-provider-google/issues/1396))
* container: Support regional clusters for node pools. ([#1320](https://github.com/terraform-providers/terraform-provider-google/issues/1320))
* all: List of resources is now partially auto-generated ([#1397](https://github.com/terraform-providers/terraform-provider-google/issues/1397)] [[#1402](https://github.com/terraform-providers/terraform-provider-google/issues/1402))
BUG FIXES:
* iam: expand the validation for service accounts to include App Engine and compute default service accounts ([#1390](https://github.com/terraform-providers/terraform-provider-google/issues/1390))
* sql: Increase timeouts ([#1381](https://github.com/terraform-providers/terraform-provider-google/issues/1381))
* website: fix broken layouts ([#1405](https://github.com/terraform-providers/terraform-provider-google/issues/1405))
## 1.10.0 (April 20, 2018) ## 1.10.0 (April 20, 2018)

View File

@ -1,5 +1,7 @@
TEST?=$$(go list ./... |grep -v 'vendor') TEST?=$$(go list ./... |grep -v 'vendor')
GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor) GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor)
WEBSITE_REPO=github.com/hashicorp/terraform-website
PKG_NAME=google
default: build default: build
@ -38,10 +40,24 @@ vendor-status:
test-compile: test-compile:
@if [ "$(TEST)" = "./..." ]; then \ @if [ "$(TEST)" = "./..." ]; then \
echo "ERROR: Set TEST to a specific package. For example,"; \ echo "ERROR: Set TEST to a specific package. For example,"; \
echo " make test-compile TEST=./aws"; \ echo " make test-compile TEST=./$(PKG_NAME)"; \
exit 1; \ exit 1; \
fi fi
go test -c $(TEST) $(TESTARGS) go test -c $(TEST) $(TESTARGS)
.PHONY: build test testacc vet fmt fmtcheck errcheck vendor-status test-compile website:
ifeq (,$(wildcard $(GOPATH)/src/$(WEBSITE_REPO)))
echo "$(WEBSITE_REPO) not found in your GOPATH (necessary for layouts and assets), get-ting..."
git clone https://$(WEBSITE_REPO) $(GOPATH)/src/$(WEBSITE_REPO)
endif
@$(MAKE) -C $(GOPATH)/src/$(WEBSITE_REPO) website-provider PROVIDER_PATH=$(shell pwd) PROVIDER_NAME=$(PKG_NAME)
website-test:
ifeq (,$(wildcard $(GOPATH)/src/$(WEBSITE_REPO)))
echo "$(WEBSITE_REPO) not found in your GOPATH (necessary for layouts and assets), get-ting..."
git clone https://$(WEBSITE_REPO) $(GOPATH)/src/$(WEBSITE_REPO)
endif
@$(MAKE) -C $(GOPATH)/src/$(WEBSITE_REPO) website-provider-test PROVIDER_PATH=$(shell pwd) PROVIDER_NAME=$(PKG_NAME)
.PHONY: build test testacc vet fmt fmtcheck errcheck vendor-status test-compile website website-test

View File

@ -106,7 +106,7 @@ func expandAccessConfigs(configs []interface{}) []*computeBeta.AccessConfig {
Type: "ONE_TO_ONE_NAT", Type: "ONE_TO_ONE_NAT",
NatIP: data["nat_ip"].(string), NatIP: data["nat_ip"].(string),
} }
if ptr, ok := data["public_ptr_domain_name"]; ok { if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" {
acs[i].SetPublicPtr = true acs[i].SetPublicPtr = true
acs[i].PublicPtrDomainName = ptr.(string) acs[i].PublicPtrDomainName = ptr.(string)
} }

View File

@ -59,6 +59,7 @@ func testAccDataSourceGoogleContainerClusterCheck(dataSourceName string, resourc
"master_auth", "master_auth",
"master_auth.0.password", "master_auth.0.password",
"master_auth.0.username", "master_auth.0.username",
"master_auth.0.client_certificate_config.0.issue_client_certificate",
"master_auth.0.client_certificate", "master_auth.0.client_certificate",
"master_auth.0.client_key", "master_auth.0.client_key",
"master_auth.0.cluster_ca_certificate", "master_auth.0.cluster_ca_certificate",

View File

@ -0,0 +1,141 @@
package google
import (
"fmt"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudresourcemanager/v1"
spanner "google.golang.org/api/spanner/v1"
)
var IamSpannerDatabaseSchema = map[string]*schema.Schema{
"instance": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"database": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
}
type SpannerDatabaseIamUpdater struct {
project string
instance string
database string
Config *Config
}
func NewSpannerDatabaseIamUpdater(d *schema.ResourceData, config *Config) (ResourceIamUpdater, error) {
project, err := getProject(d, config)
if err != nil {
return nil, err
}
return &SpannerDatabaseIamUpdater{
project: project,
instance: d.Get("instance").(string),
database: d.Get("database").(string),
Config: config,
}, nil
}
func SpannerDatabaseIdParseFunc(d *schema.ResourceData, config *Config) error {
id, err := extractSpannerDatabaseId(d.Id())
if err != nil {
return err
}
d.Set("instance", id.Instance)
d.Set("project", id.Project)
d.Set("database", id.Database)
// Explicitly set the id so imported resources have the same ID format as non-imported ones.
d.SetId(id.terraformId())
return nil
}
func (u *SpannerDatabaseIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
p, err := u.Config.clientSpanner.Projects.Instances.Databases.GetIamPolicy(spannerDatabaseId{
Project: u.project,
Database: u.database,
Instance: u.instance,
}.databaseUri(), &spanner.GetIamPolicyRequest{}).Do()
if err != nil {
return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err)
}
cloudResourcePolicy, err := spannerToResourceManagerPolicy(p)
if err != nil {
return nil, errwrap.Wrapf(fmt.Sprintf("Invalid IAM policy for %s: {{err}}", u.DescribeResource()), err)
}
return cloudResourcePolicy, nil
}
func (u *SpannerDatabaseIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
spannerPolicy, err := resourceManagerToSpannerPolicy(policy)
if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Invalid IAM policy for %s: {{err}}", u.DescribeResource()), err)
}
_, err = u.Config.clientSpanner.Projects.Instances.Databases.SetIamPolicy(spannerDatabaseId{
Project: u.project,
Database: u.database,
Instance: u.instance,
}.databaseUri(), &spanner.SetIamPolicyRequest{
Policy: spannerPolicy,
}).Do()
if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{err}}", u.DescribeResource()), err)
}
return nil
}
func (u *SpannerDatabaseIamUpdater) GetResourceId() string {
return spannerDatabaseId{
Project: u.project,
Instance: u.instance,
Database: u.database,
}.terraformId()
}
func (u *SpannerDatabaseIamUpdater) GetMutexKey() string {
return fmt.Sprintf("iam-spanner-database-%s-%s-%s", u.project, u.instance, u.database)
}
func (u *SpannerDatabaseIamUpdater) DescribeResource() string {
return fmt.Sprintf("Spanner Database: %s/%s/%s", u.project, u.instance, u.database)
}
func resourceManagerToSpannerPolicy(p *cloudresourcemanager.Policy) (*spanner.Policy, error) {
out := &spanner.Policy{}
err := Convert(p, out)
if err != nil {
return nil, errwrap.Wrapf("Cannot convert a resourcemanager policy to a spanner policy: {{err}}", err)
}
return out, nil
}
func spannerToResourceManagerPolicy(p *spanner.Policy) (*cloudresourcemanager.Policy, error) {
out := &cloudresourcemanager.Policy{}
err := Convert(p, out)
if err != nil {
return nil, errwrap.Wrapf("Cannot convert a spanner policy to a resourcemanager policy: {{err}}", err)
}
return out, nil
}

View File

@ -93,130 +93,130 @@ func Provider() terraform.ResourceProvider {
"google_compute_backend_service": dataSourceGoogleComputeBackendService(), "google_compute_backend_service": dataSourceGoogleComputeBackendService(),
}, },
ResourcesMap: map[string]*schema.Resource{ ResourcesMap: mergeResourceMaps(
"google_bigquery_dataset": resourceBigQueryDataset(), GeneratedComputeResourcesMap,
"google_bigquery_table": resourceBigQueryTable(), map[string]*schema.Resource{
"google_bigtable_instance": resourceBigtableInstance(), "google_bigquery_dataset": resourceBigQueryDataset(),
"google_bigtable_table": resourceBigtableTable(), "google_bigquery_table": resourceBigQueryTable(),
"google_cloudfunctions_function": resourceCloudFunctionsFunction(), "google_bigtable_instance": resourceBigtableInstance(),
"google_cloudiot_registry": resourceCloudIoTRegistry(), "google_bigtable_table": resourceBigtableTable(),
"google_compute_autoscaler": resourceComputeAutoscaler(), "google_cloudfunctions_function": resourceCloudFunctionsFunction(),
"google_compute_address": resourceComputeAddress(), "google_cloudiot_registry": resourceCloudIoTRegistry(),
"google_compute_backend_bucket": resourceComputeBackendBucket(), "google_compute_autoscaler": resourceComputeAutoscaler(),
"google_compute_backend_service": resourceComputeBackendService(), "google_compute_address": resourceComputeAddress(),
"google_compute_disk": resourceComputeDisk(), "google_compute_backend_service": resourceComputeBackendService(),
"google_compute_snapshot": resourceComputeSnapshot(), "google_compute_disk": resourceComputeDisk(),
"google_compute_firewall": resourceComputeFirewall(), "google_compute_snapshot": resourceComputeSnapshot(),
"google_compute_forwarding_rule": resourceComputeForwardingRule(), "google_compute_firewall": resourceComputeFirewall(),
"google_compute_global_address": resourceComputeGlobalAddress(), "google_compute_forwarding_rule": resourceComputeForwardingRule(),
"google_compute_global_forwarding_rule": resourceComputeGlobalForwardingRule(), "google_compute_global_forwarding_rule": resourceComputeGlobalForwardingRule(),
"google_compute_health_check": resourceComputeHealthCheck(), "google_compute_health_check": resourceComputeHealthCheck(),
"google_compute_http_health_check": resourceComputeHttpHealthCheck(), "google_compute_image": resourceComputeImage(),
"google_compute_https_health_check": resourceComputeHttpsHealthCheck(), "google_compute_instance": resourceComputeInstance(),
"google_compute_image": resourceComputeImage(), "google_compute_instance_group": resourceComputeInstanceGroup(),
"google_compute_instance": resourceComputeInstance(), "google_compute_instance_group_manager": resourceComputeInstanceGroupManager(),
"google_compute_instance_group": resourceComputeInstanceGroup(), "google_compute_instance_template": resourceComputeInstanceTemplate(),
"google_compute_instance_group_manager": resourceComputeInstanceGroupManager(), "google_compute_network": resourceComputeNetwork(),
"google_compute_instance_template": resourceComputeInstanceTemplate(), "google_compute_network_peering": resourceComputeNetworkPeering(),
"google_compute_network": resourceComputeNetwork(), "google_compute_project_metadata": resourceComputeProjectMetadata(),
"google_compute_network_peering": resourceComputeNetworkPeering(), "google_compute_project_metadata_item": resourceComputeProjectMetadataItem(),
"google_compute_project_metadata": resourceComputeProjectMetadata(), "google_compute_region_autoscaler": resourceComputeRegionAutoscaler(),
"google_compute_project_metadata_item": resourceComputeProjectMetadataItem(), "google_compute_region_backend_service": resourceComputeRegionBackendService(),
"google_compute_region_autoscaler": resourceComputeRegionAutoscaler(), "google_compute_region_instance_group_manager": resourceComputeRegionInstanceGroupManager(),
"google_compute_region_backend_service": resourceComputeRegionBackendService(), "google_compute_route": resourceComputeRoute(),
"google_compute_region_instance_group_manager": resourceComputeRegionInstanceGroupManager(), "google_compute_router": resourceComputeRouter(),
"google_compute_route": resourceComputeRoute(), "google_compute_router_interface": resourceComputeRouterInterface(),
"google_compute_router": resourceComputeRouter(), "google_compute_router_peer": resourceComputeRouterPeer(),
"google_compute_router_interface": resourceComputeRouterInterface(), "google_compute_security_policy": resourceComputeSecurityPolicy(),
"google_compute_router_peer": resourceComputeRouterPeer(), "google_compute_shared_vpc_host_project": resourceComputeSharedVpcHostProject(),
"google_compute_security_policy": resourceComputeSecurityPolicy(), "google_compute_shared_vpc_service_project": resourceComputeSharedVpcServiceProject(),
"google_compute_shared_vpc_host_project": resourceComputeSharedVpcHostProject(), "google_compute_ssl_certificate": resourceComputeSslCertificate(),
"google_compute_shared_vpc_service_project": resourceComputeSharedVpcServiceProject(), "google_compute_ssl_policy": resourceComputeSslPolicy(),
"google_compute_ssl_certificate": resourceComputeSslCertificate(), "google_compute_subnetwork": resourceComputeSubnetwork(),
"google_compute_ssl_policy": resourceComputeSslPolicy(), "google_compute_subnetwork_iam_binding": ResourceIamBindingWithImport(IamComputeSubnetworkSchema, NewComputeSubnetworkIamUpdater, ComputeSubnetworkIdParseFunc),
"google_compute_subnetwork": resourceComputeSubnetwork(), "google_compute_subnetwork_iam_member": ResourceIamMemberWithImport(IamComputeSubnetworkSchema, NewComputeSubnetworkIamUpdater, ComputeSubnetworkIdParseFunc),
"google_compute_subnetwork_iam_binding": ResourceIamBindingWithImport(IamComputeSubnetworkSchema, NewComputeSubnetworkIamUpdater, ComputeSubnetworkIdParseFunc), "google_compute_subnetwork_iam_policy": ResourceIamPolicyWithImport(IamComputeSubnetworkSchema, NewComputeSubnetworkIamUpdater, ComputeSubnetworkIdParseFunc),
"google_compute_subnetwork_iam_member": ResourceIamMemberWithImport(IamComputeSubnetworkSchema, NewComputeSubnetworkIamUpdater, ComputeSubnetworkIdParseFunc), "google_compute_target_https_proxy": resourceComputeTargetHttpsProxy(),
"google_compute_subnetwork_iam_policy": ResourceIamPolicyWithImport(IamComputeSubnetworkSchema, NewComputeSubnetworkIamUpdater, ComputeSubnetworkIdParseFunc), "google_compute_target_tcp_proxy": resourceComputeTargetTcpProxy(),
"google_compute_target_http_proxy": resourceComputeTargetHttpProxy(), "google_compute_target_pool": resourceComputeTargetPool(),
"google_compute_target_https_proxy": resourceComputeTargetHttpsProxy(), "google_compute_url_map": resourceComputeUrlMap(),
"google_compute_target_tcp_proxy": resourceComputeTargetTcpProxy(), "google_compute_vpn_gateway": resourceComputeVpnGateway(),
"google_compute_target_ssl_proxy": resourceComputeTargetSslProxy(), "google_compute_vpn_tunnel": resourceComputeVpnTunnel(),
"google_compute_target_pool": resourceComputeTargetPool(), "google_container_cluster": resourceContainerCluster(),
"google_compute_url_map": resourceComputeUrlMap(), "google_container_node_pool": resourceContainerNodePool(),
"google_compute_vpn_gateway": resourceComputeVpnGateway(), "google_dataflow_job": resourceDataflowJob(),
"google_compute_vpn_tunnel": resourceComputeVpnTunnel(), "google_dataproc_cluster": resourceDataprocCluster(),
"google_container_cluster": resourceContainerCluster(), "google_dataproc_job": resourceDataprocJob(),
"google_container_node_pool": resourceContainerNodePool(), "google_dns_managed_zone": resourceDnsManagedZone(),
"google_dataflow_job": resourceDataflowJob(), "google_dns_record_set": resourceDnsRecordSet(),
"google_dataproc_cluster": resourceDataprocCluster(), "google_endpoints_service": resourceEndpointsService(),
"google_dataproc_job": resourceDataprocJob(), "google_folder": resourceGoogleFolder(),
"google_dns_managed_zone": resourceDnsManagedZone(), "google_folder_iam_binding": ResourceIamBindingWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
"google_dns_record_set": resourceDnsRecordSet(), "google_folder_iam_member": ResourceIamMemberWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
"google_endpoints_service": resourceEndpointsService(), "google_folder_iam_policy": ResourceIamPolicyWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
"google_folder": resourceGoogleFolder(), "google_folder_organization_policy": resourceGoogleFolderOrganizationPolicy(),
"google_folder_iam_binding": ResourceIamBindingWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc), "google_logging_billing_account_sink": resourceLoggingBillingAccountSink(),
"google_folder_iam_member": ResourceIamMemberWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc), "google_logging_organization_sink": resourceLoggingOrganizationSink(),
"google_folder_iam_policy": ResourceIamPolicyWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc), "google_logging_folder_sink": resourceLoggingFolderSink(),
"google_folder_organization_policy": resourceGoogleFolderOrganizationPolicy(), "google_logging_project_sink": resourceLoggingProjectSink(),
"google_logging_billing_account_sink": resourceLoggingBillingAccountSink(), "google_kms_key_ring": resourceKmsKeyRing(),
"google_logging_organization_sink": resourceLoggingOrganizationSink(), "google_kms_key_ring_iam_binding": ResourceIamBindingWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc),
"google_logging_folder_sink": resourceLoggingFolderSink(), "google_kms_key_ring_iam_member": ResourceIamMemberWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc),
"google_logging_project_sink": resourceLoggingProjectSink(), "google_kms_key_ring_iam_policy": ResourceIamPolicyWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc),
"google_kms_key_ring": resourceKmsKeyRing(), "google_kms_crypto_key": resourceKmsCryptoKey(),
"google_kms_key_ring_iam_binding": ResourceIamBindingWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc), "google_kms_crypto_key_iam_binding": ResourceIamBindingWithImport(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
"google_kms_key_ring_iam_member": ResourceIamMemberWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc), "google_kms_crypto_key_iam_member": ResourceIamMemberWithImport(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
"google_kms_key_ring_iam_policy": ResourceIamPolicyWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc), "google_sourcerepo_repository": resourceSourceRepoRepository(),
"google_kms_crypto_key": resourceKmsCryptoKey(), "google_spanner_instance": resourceSpannerInstance(),
"google_kms_crypto_key_iam_binding": ResourceIamBindingWithImport(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc), "google_spanner_database": resourceSpannerDatabase(),
"google_kms_crypto_key_iam_member": ResourceIamMemberWithImport(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc), "google_spanner_database_iam_binding": ResourceIamBindingWithImport(IamSpannerDatabaseSchema, NewSpannerDatabaseIamUpdater, SpannerDatabaseIdParseFunc),
"google_sourcerepo_repository": resourceSourceRepoRepository(), "google_spanner_database_iam_member": ResourceIamMemberWithImport(IamSpannerDatabaseSchema, NewSpannerDatabaseIamUpdater, SpannerDatabaseIdParseFunc),
"google_spanner_instance": resourceSpannerInstance(), "google_spanner_database_iam_policy": ResourceIamPolicyWithImport(IamSpannerDatabaseSchema, NewSpannerDatabaseIamUpdater, SpannerDatabaseIdParseFunc),
"google_spanner_database": resourceSpannerDatabase(), "google_sql_database": resourceSqlDatabase(),
"google_sql_database": resourceSqlDatabase(), "google_sql_database_instance": resourceSqlDatabaseInstance(),
"google_sql_database_instance": resourceSqlDatabaseInstance(), "google_sql_user": resourceSqlUser(),
"google_sql_user": resourceSqlUser(), "google_organization_iam_binding": ResourceIamBindingWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc),
"google_organization_iam_binding": ResourceIamBindingWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc), "google_organization_iam_custom_role": resourceGoogleOrganizationIamCustomRole(),
"google_organization_iam_custom_role": resourceGoogleOrganizationIamCustomRole(), "google_organization_iam_member": ResourceIamMemberWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc),
"google_organization_iam_member": ResourceIamMemberWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc), "google_organization_iam_policy": ResourceIamPolicyWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc),
"google_organization_iam_policy": ResourceIamPolicyWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc), "google_organization_policy": resourceGoogleOrganizationPolicy(),
"google_organization_policy": resourceGoogleOrganizationPolicy(), "google_project": resourceGoogleProject(),
"google_project": resourceGoogleProject(), "google_project_iam_policy": resourceGoogleProjectIamPolicy(),
"google_project_iam_policy": resourceGoogleProjectIamPolicy(), "google_project_iam_binding": ResourceIamBindingWithImport(IamProjectSchema, NewProjectIamUpdater, ProjectIdParseFunc),
"google_project_iam_binding": ResourceIamBindingWithImport(IamProjectSchema, NewProjectIamUpdater, ProjectIdParseFunc), "google_project_iam_member": ResourceIamMemberWithImport(IamProjectSchema, NewProjectIamUpdater, ProjectIdParseFunc),
"google_project_iam_member": ResourceIamMemberWithImport(IamProjectSchema, NewProjectIamUpdater, ProjectIdParseFunc), "google_project_service": resourceGoogleProjectService(),
"google_project_service": resourceGoogleProjectService(), "google_project_iam_custom_role": resourceGoogleProjectIamCustomRole(),
"google_project_iam_custom_role": resourceGoogleProjectIamCustomRole(), "google_project_organization_policy": resourceGoogleProjectOrganizationPolicy(),
"google_project_organization_policy": resourceGoogleProjectOrganizationPolicy(), "google_project_usage_export_bucket": resourceProjectUsageBucket(),
"google_project_usage_export_bucket": resourceProjectUsageBucket(), "google_project_services": resourceGoogleProjectServices(),
"google_project_services": resourceGoogleProjectServices(), "google_pubsub_topic": resourcePubsubTopic(),
"google_pubsub_topic": resourcePubsubTopic(), "google_pubsub_topic_iam_binding": ResourceIamBindingWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc),
"google_pubsub_topic_iam_binding": ResourceIamBindingWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc), "google_pubsub_topic_iam_member": ResourceIamMemberWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc),
"google_pubsub_topic_iam_member": ResourceIamMemberWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc), "google_pubsub_topic_iam_policy": ResourceIamPolicyWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc),
"google_pubsub_topic_iam_policy": ResourceIamPolicyWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc), "google_pubsub_subscription": resourcePubsubSubscription(),
"google_pubsub_subscription": resourcePubsubSubscription(), "google_pubsub_subscription_iam_binding": ResourceIamBindingWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
"google_pubsub_subscription_iam_binding": ResourceIamBindingWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc), "google_pubsub_subscription_iam_member": ResourceIamMemberWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
"google_pubsub_subscription_iam_member": ResourceIamMemberWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc), "google_pubsub_subscription_iam_policy": ResourceIamPolicyWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
"google_pubsub_subscription_iam_policy": ResourceIamPolicyWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc), "google_runtimeconfig_config": resourceRuntimeconfigConfig(),
"google_runtimeconfig_config": resourceRuntimeconfigConfig(), "google_runtimeconfig_variable": resourceRuntimeconfigVariable(),
"google_runtimeconfig_variable": resourceRuntimeconfigVariable(), "google_service_account": resourceGoogleServiceAccount(),
"google_service_account": resourceGoogleServiceAccount(), "google_service_account_iam_binding": ResourceIamBindingWithImport(IamServiceAccountSchema, NewServiceAccountIamUpdater, ServiceAccountIdParseFunc),
"google_service_account_iam_binding": ResourceIamBindingWithImport(IamServiceAccountSchema, NewServiceAccountIamUpdater, ServiceAccountIdParseFunc), "google_service_account_iam_member": ResourceIamMemberWithImport(IamServiceAccountSchema, NewServiceAccountIamUpdater, ServiceAccountIdParseFunc),
"google_service_account_iam_member": ResourceIamMemberWithImport(IamServiceAccountSchema, NewServiceAccountIamUpdater, ServiceAccountIdParseFunc), "google_service_account_iam_policy": ResourceIamPolicyWithImport(IamServiceAccountSchema, NewServiceAccountIamUpdater, ServiceAccountIdParseFunc),
"google_service_account_iam_policy": ResourceIamPolicyWithImport(IamServiceAccountSchema, NewServiceAccountIamUpdater, ServiceAccountIdParseFunc), "google_service_account_key": resourceGoogleServiceAccountKey(),
"google_service_account_key": resourceGoogleServiceAccountKey(), "google_storage_bucket": resourceStorageBucket(),
"google_storage_bucket": resourceStorageBucket(), "google_storage_bucket_acl": resourceStorageBucketAcl(),
"google_storage_bucket_acl": resourceStorageBucketAcl(), // Legacy roles such as roles/storage.legacyBucketReader are automatically added
// Legacy roles such as roles/storage.legacyBucketReader are automatically added // when creating a bucket. For this reason, it is better not to add the authoritative
// when creating a bucket. For this reason, it is better not to add the authoritative // google_storage_bucket_iam_policy resource.
// google_storage_bucket_iam_policy resource. "google_storage_bucket_iam_binding": ResourceIamBinding(IamStorageBucketSchema, NewStorageBucketIamUpdater),
"google_storage_bucket_iam_binding": ResourceIamBinding(IamStorageBucketSchema, NewStorageBucketIamUpdater), "google_storage_bucket_iam_member": ResourceIamMember(IamStorageBucketSchema, NewStorageBucketIamUpdater),
"google_storage_bucket_iam_member": ResourceIamMember(IamStorageBucketSchema, NewStorageBucketIamUpdater), "google_storage_bucket_object": resourceStorageBucketObject(),
"google_storage_bucket_object": resourceStorageBucketObject(), "google_storage_object_acl": resourceStorageObjectAcl(),
"google_storage_object_acl": resourceStorageObjectAcl(), "google_storage_default_object_acl": resourceStorageDefaultObjectAcl(),
"google_storage_default_object_acl": resourceStorageDefaultObjectAcl(), "google_storage_notification": resourceStorageNotification(),
"google_storage_notification": resourceStorageNotification(), },
}, ),
ConfigureFunc: providerConfigure, ConfigureFunc: providerConfigure,
} }

View File

@ -0,0 +1,29 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import "github.com/hashicorp/terraform/helper/schema"
var GeneratedComputeResourcesMap = map[string]*schema.Resource{
"google_compute_backend_bucket": resourceComputeBackendBucket(),
"google_compute_global_address": resourceComputeGlobalAddress(),
"google_compute_http_health_check": resourceComputeHttpHealthCheck(),
"google_compute_https_health_check": resourceComputeHttpsHealthCheck(),
"google_compute_target_http_proxy": resourceComputeTargetHttpProxy(),
"google_compute_target_https_proxy": resourceComputeTargetHttpsProxy(),
"google_compute_target_ssl_proxy": resourceComputeTargetSslProxy(),
"google_compute_target_tcp_proxy": resourceComputeTargetTcpProxy(),
"google_compute_vpn_gateway": resourceComputeVpnGateway(),
}

View File

@ -7,7 +7,6 @@ import (
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation" "github.com/hashicorp/terraform/helper/validation"
computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1" "google.golang.org/api/compute/v1"
) )
@ -19,11 +18,6 @@ const (
var ( var (
computeAddressIdTemplate = "projects/%s/regions/%s/addresses/%s" computeAddressIdTemplate = "projects/%s/regions/%s/addresses/%s"
computeAddressLinkRegex = regexp.MustCompile("projects/(.+)/regions/(.+)/addresses/(.+)$") computeAddressLinkRegex = regexp.MustCompile("projects/(.+)/regions/(.+)/addresses/(.+)$")
AddressBaseApiVersion = v1
AddressVersionedFeatures = []Feature{
{Version: v0beta, Item: "address_type", DefaultValue: addressTypeExternal},
{Version: v0beta, Item: "subnetwork"},
}
) )
func resourceComputeAddress() *schema.Resource { func resourceComputeAddress() *schema.Resource {
@ -96,7 +90,6 @@ func resourceComputeAddress() *schema.Resource {
} }
func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) error { func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, AddressBaseApiVersion, AddressVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
region, err := getRegion(d, config) region, err := getRegion(d, config)
@ -110,30 +103,14 @@ func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) erro
} }
// Build the address parameter // Build the address parameter
v0BetaAddress := &computeBeta.Address{ address := &compute.Address{
Name: d.Get("name").(string), Name: d.Get("name").(string),
AddressType: d.Get("address_type").(string), AddressType: d.Get("address_type").(string),
Subnetwork: d.Get("subnetwork").(string), Subnetwork: d.Get("subnetwork").(string),
Address: d.Get("address").(string),
} }
if desired, ok := d.GetOk("address"); ok { op, err := config.clientCompute.Addresses.Insert(project, region, address).Do()
v0BetaAddress.Address = desired.(string)
}
var op interface{}
switch computeApiVersion {
case v1:
v1Address := &compute.Address{}
err = Convert(v0BetaAddress, v1Address)
if err != nil {
return err
}
op, err = config.clientCompute.Addresses.Insert(
project, region, v1Address).Do()
case v0beta:
op, err = config.clientComputeBeta.Addresses.Insert(
project, region, v0BetaAddress).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error creating address: %s", err) return fmt.Errorf("Error creating address: %s", err)
} }
@ -142,7 +119,7 @@ func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) erro
d.SetId(computeAddressId{ d.SetId(computeAddressId{
Project: project, Project: project,
Region: region, Region: region,
Name: v0BetaAddress.Name, Name: address.Name,
}.canonicalId()) }.canonicalId())
err = computeSharedOperationWait(config.clientCompute, op, project, "Creating Address") err = computeSharedOperationWait(config.clientCompute, op, project, "Creating Address")
@ -154,7 +131,6 @@ func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) erro
} }
func resourceComputeAddressRead(d *schema.ResourceData, meta interface{}) error { func resourceComputeAddressRead(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, AddressBaseApiVersion, AddressVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
addressId, err := parseComputeAddressId(d.Id(), config) addressId, err := parseComputeAddressId(d.Id(), config)
@ -162,28 +138,10 @@ func resourceComputeAddressRead(d *schema.ResourceData, meta interface{}) error
return err return err
} }
addr := &computeBeta.Address{} addr, err := config.clientCompute.Addresses.Get(
switch computeApiVersion { addressId.Project, addressId.Region, addressId.Name).Do()
case v1: if err != nil {
v1Address, err := config.clientCompute.Addresses.Get( return handleNotFoundError(err, d, fmt.Sprintf("Address %q", d.Get("name").(string)))
addressId.Project, addressId.Region, addressId.Name).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Address %q", d.Get("name").(string)))
}
err = Convert(v1Address, addr)
if err != nil {
return err
}
case v0beta:
var err error
addr, err = config.clientComputeBeta.Addresses.Get(
addressId.Project, addressId.Region, addressId.Name).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Address %q", d.Get("name").(string)))
}
} }
// The v1 API does not include an AddressType field, as it only supports // The v1 API does not include an AddressType field, as it only supports
@ -204,7 +162,6 @@ func resourceComputeAddressRead(d *schema.ResourceData, meta interface{}) error
} }
func resourceComputeAddressDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeAddressDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, AddressBaseApiVersion, AddressVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
addressId, err := parseComputeAddressId(d.Id(), config) addressId, err := parseComputeAddressId(d.Id(), config)
@ -213,20 +170,10 @@ func resourceComputeAddressDelete(d *schema.ResourceData, meta interface{}) erro
} }
// Delete the address // Delete the address
var op interface{} op, err := config.clientCompute.Addresses.Delete(
switch computeApiVersion { addressId.Project, addressId.Region, addressId.Name).Do()
case v1: if err != nil {
op, err = config.clientCompute.Addresses.Delete( return fmt.Errorf("Error deleting address: %s", err)
addressId.Project, addressId.Region, addressId.Name).Do()
if err != nil {
return fmt.Errorf("Error deleting address: %s", err)
}
case v0beta:
op, err = config.clientComputeBeta.Addresses.Delete(
addressId.Project, addressId.Region, addressId.Name).Do()
if err != nil {
return fmt.Errorf("Error deleting address: %s", err)
}
} }
err = computeSharedOperationWait(config.clientCompute, op, addressId.Project, "Deleting Address") err = computeSharedOperationWait(config.clientCompute, op, addressId.Project, "Deleting Address")

View File

@ -140,7 +140,7 @@ func resourceComputeBackendBucketCreate(d *schema.ResourceData, meta interface{}
if waitErr != nil { if waitErr != nil {
// The resource didn't actually create // The resource didn't actually create
d.SetId("") d.SetId("")
return waitErr return fmt.Errorf("Error waiting to create BackendBucket: %s", waitErr)
} }
return resourceComputeBackendBucketRead(d, meta) return resourceComputeBackendBucketRead(d, meta)
@ -163,14 +163,27 @@ func resourceComputeBackendBucketRead(d *schema.ResourceData, meta interface{})
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("ComputeBackendBucket %q", d.Id())) return handleNotFoundError(err, d, fmt.Sprintf("ComputeBackendBucket %q", d.Id()))
} }
if err := d.Set("bucket_name", flattenComputeBackendBucketBucketName(res["bucketName"])); err != nil {
d.Set("bucket_name", flattenComputeBackendBucketBucketName(res["bucketName"])) return fmt.Errorf("Error reading BackendBucket: %s", err)
d.Set("creation_timestamp", flattenComputeBackendBucketCreationTimestamp(res["creationTimestamp"])) }
d.Set("description", flattenComputeBackendBucketDescription(res["description"])) if err := d.Set("creation_timestamp", flattenComputeBackendBucketCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("enable_cdn", flattenComputeBackendBucketEnableCdn(res["enableCdn"])) return fmt.Errorf("Error reading BackendBucket: %s", err)
d.Set("name", flattenComputeBackendBucketName(res["name"])) }
d.Set("self_link", res["selfLink"]) if err := d.Set("description", flattenComputeBackendBucketDescription(res["description"])); err != nil {
d.Set("project", project) return fmt.Errorf("Error reading BackendBucket: %s", err)
}
if err := d.Set("enable_cdn", flattenComputeBackendBucketEnableCdn(res["enableCdn"])); err != nil {
return fmt.Errorf("Error reading BackendBucket: %s", err)
}
if err := d.Set("name", flattenComputeBackendBucketName(res["name"])); err != nil {
return fmt.Errorf("Error reading BackendBucket: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading BackendBucket: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading BackendBucket: %s", err)
}
return nil return nil
} }

View File

@ -1,13 +1,27 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google package google
import ( import (
"fmt" "fmt"
"log" "log"
"time"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation" "github.com/hashicorp/terraform/helper/validation"
compute "google.golang.org/api/compute/v1"
"google.golang.org/api/compute/v1"
) )
func resourceComputeGlobalAddress() *schema.Resource { func resourceComputeGlobalAddress() *schema.Resource {
@ -15,37 +29,48 @@ func resourceComputeGlobalAddress() *schema.Resource {
Create: resourceComputeGlobalAddressCreate, Create: resourceComputeGlobalAddressCreate,
Read: resourceComputeGlobalAddressRead, Read: resourceComputeGlobalAddressRead,
Delete: resourceComputeGlobalAddressDelete, Delete: resourceComputeGlobalAddressDelete,
Importer: &schema.ResourceImporter{ Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough, State: resourceComputeGlobalAddressImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
}, },
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"description": {
"ip_version": &schema.Schema{ Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"ip_version": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"IPV4", "IPV6", ""}, false), ValidateFunc: validation.StringInSlice([]string{"IPV4", "IPV6", ""}, false),
}, },
"address": {
"project": &schema.Schema{ Type: schema.TypeString,
Computed: true,
},
"creation_timestamp": {
Type: schema.TypeString,
Computed: true,
},
"project": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"self_link": {
"address": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"self_link": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
@ -61,24 +86,58 @@ func resourceComputeGlobalAddressCreate(d *schema.ResourceData, meta interface{}
return err return err
} }
// Build the address parameter descriptionProp, err := expandComputeGlobalAddressDescription(d.Get("description"), d, config)
addr := &compute.Address{
Name: d.Get("name").(string),
IpVersion: d.Get("ip_version").(string),
}
op, err := config.clientCompute.GlobalAddresses.Insert(project, addr).Do()
if err != nil {
return fmt.Errorf("Error creating address: %s", err)
}
// It probably maybe worked, so store the ID now
d.SetId(addr.Name)
err = computeSharedOperationWait(config.clientCompute, op, project, "Creating Global Address")
if err != nil { if err != nil {
return err return err
} }
nameProp, err := expandComputeGlobalAddressName(d.Get("name"), d, config)
if err != nil {
return err
}
ipVersionProp, err := expandComputeGlobalAddressIpVersion(d.Get("ip_version"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{
"description": descriptionProp,
"name": nameProp,
"ipVersion": ipVersionProp,
}
url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/addresses")
if err != nil {
return err
}
log.Printf("[DEBUG] Creating new GlobalAddress: %#v", obj)
res, err := Post(config, url, obj)
if err != nil {
return fmt.Errorf("Error creating GlobalAddress: %s", err)
}
// Store the ID now
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
op := &compute.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
waitErr := computeOperationWaitTime(
config.clientCompute, op, project, "Creating GlobalAddress",
int(d.Timeout(schema.TimeoutCreate).Minutes()))
if waitErr != nil {
// The resource didn't actually create
d.SetId("")
return fmt.Errorf("Error waiting to create GlobalAddress: %s", waitErr)
}
return resourceComputeGlobalAddressRead(d, meta) return resourceComputeGlobalAddressRead(d, meta)
} }
@ -91,16 +150,36 @@ func resourceComputeGlobalAddressRead(d *schema.ResourceData, meta interface{})
return err return err
} }
addr, err := config.clientCompute.GlobalAddresses.Get(project, d.Id()).Do() url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/addresses/{{name}}")
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Global Address %q", d.Get("name").(string))) return err
} }
d.Set("name", addr.Name) res, err := Get(config, url)
d.Set("ip_version", addr.IpVersion) if err != nil {
d.Set("address", addr.Address) return handleNotFoundError(err, d, fmt.Sprintf("ComputeGlobalAddress %q", d.Id()))
d.Set("project", project) }
d.Set("self_link", ConvertSelfLinkToV1(addr.SelfLink)) if err := d.Set("address", flattenComputeGlobalAddressAddress(res["address"])); err != nil {
return fmt.Errorf("Error reading GlobalAddress: %s", err)
}
if err := d.Set("creation_timestamp", flattenComputeGlobalAddressCreationTimestamp(res["creationTimestamp"])); err != nil {
return fmt.Errorf("Error reading GlobalAddress: %s", err)
}
if err := d.Set("description", flattenComputeGlobalAddressDescription(res["description"])); err != nil {
return fmt.Errorf("Error reading GlobalAddress: %s", err)
}
if err := d.Set("name", flattenComputeGlobalAddressName(res["name"])); err != nil {
return fmt.Errorf("Error reading GlobalAddress: %s", err)
}
if err := d.Set("ip_version", flattenComputeGlobalAddressIpVersion(res["ipVersion"])); err != nil {
return fmt.Errorf("Error reading GlobalAddress: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading GlobalAddress: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading GlobalAddress: %s", err)
}
return nil return nil
} }
@ -113,18 +192,76 @@ func resourceComputeGlobalAddressDelete(d *schema.ResourceData, meta interface{}
return err return err
} }
// Delete the address url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/addresses/{{name}}")
log.Printf("[DEBUG] address delete request") if err != nil {
op, err := config.clientCompute.GlobalAddresses.Delete(project, d.Id()).Do() return err
if err != nil { }
return fmt.Errorf("Error deleting address: %s", err)
} log.Printf("[DEBUG] Deleting GlobalAddress %q", d.Id())
res, err := Delete(config, url)
err = computeSharedOperationWait(config.clientCompute, op, project, "Deleting Global Address") if err != nil {
return fmt.Errorf("Error deleting GlobalAddress %q: %s", d.Id(), err)
}
op := &compute.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Deleting GlobalAddress",
int(d.Timeout(schema.TimeoutDelete).Minutes()))
if err != nil { if err != nil {
return err return err
} }
d.SetId("")
return nil return nil
} }
func resourceComputeGlobalAddressImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
parseImportId([]string{"projects/(?P<project>[^/]+)/global/addresses/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config)
// Replace import id for the resource id
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenComputeGlobalAddressAddress(v interface{}) interface{} {
return v
}
func flattenComputeGlobalAddressCreationTimestamp(v interface{}) interface{} {
return v
}
func flattenComputeGlobalAddressDescription(v interface{}) interface{} {
return v
}
func flattenComputeGlobalAddressName(v interface{}) interface{} {
return v
}
func flattenComputeGlobalAddressIpVersion(v interface{}) interface{} {
return v
}
func expandComputeGlobalAddressDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeGlobalAddressName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeGlobalAddressIpVersion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}

View File

@ -144,6 +144,7 @@ func testAccComputeGlobalAddress_basic() string {
return fmt.Sprintf(` return fmt.Sprintf(`
resource "google_compute_global_address" "foobar" { resource "google_compute_global_address" "foobar" {
name = "address-test-%s" name = "address-test-%s"
description = "Created for Terraform acceptance testing"
}`, acctest.RandString(10)) }`, acctest.RandString(10))
} }
@ -151,6 +152,7 @@ func testAccComputeGlobalAddress_ipv6() string {
return fmt.Sprintf(` return fmt.Sprintf(`
resource "google_compute_global_address" "foobar" { resource "google_compute_global_address" "foobar" {
name = "address-test-%s" name = "address-test-%s"
description = "Created for Terraform acceptance testing"
ip_version = "IPV6" ip_version = "IPV6"
}`, acctest.RandString(10)) }`, acctest.RandString(10))
} }

View File

@ -191,7 +191,7 @@ func resourceComputeHttpHealthCheckCreate(d *schema.ResourceData, meta interface
if waitErr != nil { if waitErr != nil {
// The resource didn't actually create // The resource didn't actually create
d.SetId("") d.SetId("")
return waitErr return fmt.Errorf("Error waiting to create HttpHealthCheck: %s", waitErr)
} }
return resourceComputeHttpHealthCheckRead(d, meta) return resourceComputeHttpHealthCheckRead(d, meta)
@ -214,19 +214,42 @@ func resourceComputeHttpHealthCheckRead(d *schema.ResourceData, meta interface{}
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("ComputeHttpHealthCheck %q", d.Id())) return handleNotFoundError(err, d, fmt.Sprintf("ComputeHttpHealthCheck %q", d.Id()))
} }
if err := d.Set("check_interval_sec", flattenComputeHttpHealthCheckCheckIntervalSec(res["checkIntervalSec"])); err != nil {
d.Set("check_interval_sec", flattenComputeHttpHealthCheckCheckIntervalSec(res["checkIntervalSec"])) return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
d.Set("creation_timestamp", flattenComputeHttpHealthCheckCreationTimestamp(res["creationTimestamp"])) }
d.Set("description", flattenComputeHttpHealthCheckDescription(res["description"])) if err := d.Set("creation_timestamp", flattenComputeHttpHealthCheckCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("healthy_threshold", flattenComputeHttpHealthCheckHealthyThreshold(res["healthyThreshold"])) return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
d.Set("host", flattenComputeHttpHealthCheckHost(res["host"])) }
d.Set("name", flattenComputeHttpHealthCheckName(res["name"])) if err := d.Set("description", flattenComputeHttpHealthCheckDescription(res["description"])); err != nil {
d.Set("port", flattenComputeHttpHealthCheckPort(res["port"])) return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
d.Set("request_path", flattenComputeHttpHealthCheckRequestPath(res["requestPath"])) }
d.Set("timeout_sec", flattenComputeHttpHealthCheckTimeoutSec(res["timeoutSec"])) if err := d.Set("healthy_threshold", flattenComputeHttpHealthCheckHealthyThreshold(res["healthyThreshold"])); err != nil {
d.Set("unhealthy_threshold", flattenComputeHttpHealthCheckUnhealthyThreshold(res["unhealthyThreshold"])) return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
d.Set("self_link", res["selfLink"]) }
d.Set("project", project) if err := d.Set("host", flattenComputeHttpHealthCheckHost(res["host"])); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
if err := d.Set("name", flattenComputeHttpHealthCheckName(res["name"])); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
if err := d.Set("port", flattenComputeHttpHealthCheckPort(res["port"])); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
if err := d.Set("request_path", flattenComputeHttpHealthCheckRequestPath(res["requestPath"])); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
if err := d.Set("timeout_sec", flattenComputeHttpHealthCheckTimeoutSec(res["timeoutSec"])); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
if err := d.Set("unhealthy_threshold", flattenComputeHttpHealthCheckUnhealthyThreshold(res["unhealthyThreshold"])); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading HttpHealthCheck: %s", err)
}
return nil return nil
} }

View File

@ -191,7 +191,7 @@ func resourceComputeHttpsHealthCheckCreate(d *schema.ResourceData, meta interfac
if waitErr != nil { if waitErr != nil {
// The resource didn't actually create // The resource didn't actually create
d.SetId("") d.SetId("")
return waitErr return fmt.Errorf("Error waiting to create HttpsHealthCheck: %s", waitErr)
} }
return resourceComputeHttpsHealthCheckRead(d, meta) return resourceComputeHttpsHealthCheckRead(d, meta)
@ -214,19 +214,42 @@ func resourceComputeHttpsHealthCheckRead(d *schema.ResourceData, meta interface{
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("ComputeHttpsHealthCheck %q", d.Id())) return handleNotFoundError(err, d, fmt.Sprintf("ComputeHttpsHealthCheck %q", d.Id()))
} }
if err := d.Set("check_interval_sec", flattenComputeHttpsHealthCheckCheckIntervalSec(res["checkIntervalSec"])); err != nil {
d.Set("check_interval_sec", flattenComputeHttpsHealthCheckCheckIntervalSec(res["checkIntervalSec"])) return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
d.Set("creation_timestamp", flattenComputeHttpsHealthCheckCreationTimestamp(res["creationTimestamp"])) }
d.Set("description", flattenComputeHttpsHealthCheckDescription(res["description"])) if err := d.Set("creation_timestamp", flattenComputeHttpsHealthCheckCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("healthy_threshold", flattenComputeHttpsHealthCheckHealthyThreshold(res["healthyThreshold"])) return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
d.Set("host", flattenComputeHttpsHealthCheckHost(res["host"])) }
d.Set("name", flattenComputeHttpsHealthCheckName(res["name"])) if err := d.Set("description", flattenComputeHttpsHealthCheckDescription(res["description"])); err != nil {
d.Set("port", flattenComputeHttpsHealthCheckPort(res["port"])) return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
d.Set("request_path", flattenComputeHttpsHealthCheckRequestPath(res["requestPath"])) }
d.Set("timeout_sec", flattenComputeHttpsHealthCheckTimeoutSec(res["timeoutSec"])) if err := d.Set("healthy_threshold", flattenComputeHttpsHealthCheckHealthyThreshold(res["healthyThreshold"])); err != nil {
d.Set("unhealthy_threshold", flattenComputeHttpsHealthCheckUnhealthyThreshold(res["unhealthyThreshold"])) return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
d.Set("self_link", res["selfLink"]) }
d.Set("project", project) if err := d.Set("host", flattenComputeHttpsHealthCheckHost(res["host"])); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
if err := d.Set("name", flattenComputeHttpsHealthCheckName(res["name"])); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
if err := d.Set("port", flattenComputeHttpsHealthCheckPort(res["port"])); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
if err := d.Set("request_path", flattenComputeHttpsHealthCheckRequestPath(res["requestPath"])); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
if err := d.Set("timeout_sec", flattenComputeHttpsHealthCheckTimeoutSec(res["timeoutSec"])); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
if err := d.Set("unhealthy_threshold", flattenComputeHttpsHealthCheckUnhealthyThreshold(res["unhealthyThreshold"])); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading HttpsHealthCheck: %s", err)
}
return nil return nil
} }

View File

@ -1125,7 +1125,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err
Type: "ONE_TO_ONE_NAT", Type: "ONE_TO_ONE_NAT",
NatIP: d.Get(acPrefix + ".nat_ip").(string), NatIP: d.Get(acPrefix + ".nat_ip").(string),
} }
if ptr, ok := d.GetOk(acPrefix + ".public_ptr_domain_name"); ok { if ptr, ok := d.GetOk(acPrefix + ".public_ptr_domain_name"); ok && ptr != "" {
ac.SetPublicPtr = true ac.SetPublicPtr = true
ac.PublicPtrDomainName = ptr.(string) ac.PublicPtrDomainName = ptr.(string)
} }

View File

@ -1,57 +1,77 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google package google
import ( import (
"fmt" "fmt"
"log" "log"
"strconv" "strconv"
"time"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/compute/v1" compute "google.golang.org/api/compute/v1"
) )
func resourceComputeTargetHttpProxy() *schema.Resource { func resourceComputeTargetHttpProxy() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeTargetHttpProxyCreate, Create: resourceComputeTargetHttpProxyCreate,
Read: resourceComputeTargetHttpProxyRead, Read: resourceComputeTargetHttpProxyRead,
Delete: resourceComputeTargetHttpProxyDelete,
Update: resourceComputeTargetHttpProxyUpdate, Update: resourceComputeTargetHttpProxyUpdate,
Delete: resourceComputeTargetHttpProxyDelete,
Importer: &schema.ResourceImporter{ Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough, State: resourceComputeTargetHttpProxyImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Update: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
}, },
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"url_map": {
"url_map": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
DiffSuppressFunc: compareSelfLinkRelativePaths, DiffSuppressFunc: compareSelfLinkOrResourceName,
}, },
"description": {
"description": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"creation_timestamp": {
"proxy_id": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"proxy_id": {
"project": &schema.Schema{ Type: schema.TypeInt,
Computed: true,
},
"project": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"self_link": {
"self_link": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
@ -67,61 +87,59 @@ func resourceComputeTargetHttpProxyCreate(d *schema.ResourceData, meta interface
return err return err
} }
proxy := &compute.TargetHttpProxy{ descriptionProp, err := expandComputeTargetHttpProxyDescription(d.Get("description"), d, config)
Name: d.Get("name").(string), if err != nil {
UrlMap: d.Get("url_map").(string), return err
}
nameProp, err := expandComputeTargetHttpProxyName(d.Get("name"), d, config)
if err != nil {
return err
}
urlMapProp, err := expandComputeTargetHttpProxyUrlMap(d.Get("url_map"), d, config)
if err != nil {
return err
} }
if v, ok := d.GetOk("description"); ok { obj := map[string]interface{}{
proxy.Description = v.(string) "description": descriptionProp,
"name": nameProp,
"urlMap": urlMapProp,
} }
log.Printf("[DEBUG] TargetHttpProxy insert request: %#v", proxy) url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetHttpProxies")
op, err := config.clientCompute.TargetHttpProxies.Insert( if err != nil {
project, proxy).Do() return err
}
log.Printf("[DEBUG] Creating new TargetHttpProxy: %#v", obj)
res, err := Post(config, url, obj)
if err != nil { if err != nil {
return fmt.Errorf("Error creating TargetHttpProxy: %s", err) return fmt.Errorf("Error creating TargetHttpProxy: %s", err)
} }
err = computeOperationWait(config.clientCompute, op, project, "Creating Target Http Proxy") // Store the ID now
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
op := &compute.Operation{}
err = Convert(res, op)
if err != nil { if err != nil {
return err return err
} }
d.SetId(proxy.Name) waitErr := computeOperationWaitTime(
config.clientCompute, op, project, "Creating TargetHttpProxy",
int(d.Timeout(schema.TimeoutCreate).Minutes()))
return resourceComputeTargetHttpProxyRead(d, meta) if waitErr != nil {
} // The resource didn't actually create
d.SetId("")
func resourceComputeTargetHttpProxyUpdate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error waiting to create TargetHttpProxy: %s", waitErr)
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
} }
d.Partial(true)
if d.HasChange("url_map") {
url_map := d.Get("url_map").(string)
url_map_ref := &compute.UrlMapReference{UrlMap: url_map}
op, err := config.clientCompute.TargetHttpProxies.SetUrlMap(
project, d.Id(), url_map_ref).Do()
if err != nil {
return fmt.Errorf("Error updating target: %s", err)
}
err = computeOperationWait(config.clientCompute, op, project, "Updating Target Http Proxy")
if err != nil {
return err
}
d.SetPartial("url_map")
}
d.Partial(false)
return resourceComputeTargetHttpProxyRead(d, meta) return resourceComputeTargetHttpProxyRead(d, meta)
} }
@ -133,22 +151,93 @@ func resourceComputeTargetHttpProxyRead(d *schema.ResourceData, meta interface{}
return err return err
} }
proxy, err := config.clientCompute.TargetHttpProxies.Get( url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetHttpProxies/{{name}}")
project, d.Id()).Do()
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Target HTTP Proxy %q", d.Get("name").(string))) return err
} }
d.Set("self_link", proxy.SelfLink) res, err := Get(config, url)
d.Set("proxy_id", strconv.FormatUint(proxy.Id, 10)) if err != nil {
d.Set("description", proxy.Description) return handleNotFoundError(err, d, fmt.Sprintf("ComputeTargetHttpProxy %q", d.Id()))
d.Set("url_map", proxy.UrlMap) }
d.Set("name", proxy.Name) if err := d.Set("creation_timestamp", flattenComputeTargetHttpProxyCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("project", project) return fmt.Errorf("Error reading TargetHttpProxy: %s", err)
}
if err := d.Set("description", flattenComputeTargetHttpProxyDescription(res["description"])); err != nil {
return fmt.Errorf("Error reading TargetHttpProxy: %s", err)
}
if err := d.Set("proxy_id", flattenComputeTargetHttpProxyProxyId(res["id"])); err != nil {
return fmt.Errorf("Error reading TargetHttpProxy: %s", err)
}
if err := d.Set("name", flattenComputeTargetHttpProxyName(res["name"])); err != nil {
return fmt.Errorf("Error reading TargetHttpProxy: %s", err)
}
if err := d.Set("url_map", flattenComputeTargetHttpProxyUrlMap(res["urlMap"])); err != nil {
return fmt.Errorf("Error reading TargetHttpProxy: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading TargetHttpProxy: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading TargetHttpProxy: %s", err)
}
return nil return nil
} }
func resourceComputeTargetHttpProxyUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
}
var url string
var res map[string]interface{}
op := &compute.Operation{}
d.Partial(true)
if d.HasChange("url_map") {
urlMapProp, err := expandComputeTargetHttpProxyUrlMap(d.Get("url_map"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{
"urlMap": urlMapProp,
}
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/targetHttpProxies/{{name}}/setUrlMap")
if err != nil {
return err
}
res, err = sendRequest(config, "POST", url, obj)
if err != nil {
return fmt.Errorf("Error updating TargetHttpProxy %q: %s", d.Id(), err)
}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Updating TargetHttpProxy",
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
if err != nil {
return err
}
d.SetPartial("url_map")
}
d.Partial(false)
return resourceComputeTargetHttpProxyRead(d, meta)
}
func resourceComputeTargetHttpProxyDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeTargetHttpProxyDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
@ -157,19 +246,86 @@ func resourceComputeTargetHttpProxyDelete(d *schema.ResourceData, meta interface
return err return err
} }
// Delete the TargetHttpProxy url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetHttpProxies/{{name}}")
log.Printf("[DEBUG] TargetHttpProxy delete request") if err != nil {
op, err := config.clientCompute.TargetHttpProxies.Delete( return err
project, d.Id()).Do() }
if err != nil {
return fmt.Errorf("Error deleting TargetHttpProxy: %s", err) log.Printf("[DEBUG] Deleting TargetHttpProxy %q", d.Id())
} res, err := Delete(config, url)
if err != nil {
err = computeOperationWait(config.clientCompute, op, project, "Deleting Target Http Proxy") return fmt.Errorf("Error deleting TargetHttpProxy %q: %s", d.Id(), err)
}
op := &compute.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Deleting TargetHttpProxy",
int(d.Timeout(schema.TimeoutDelete).Minutes()))
if err != nil { if err != nil {
return err return err
} }
d.SetId("")
return nil return nil
} }
func resourceComputeTargetHttpProxyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
parseImportId([]string{"projects/(?P<project>[^/]+)/global/targetHttpProxies/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config)
// Replace import id for the resource id
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenComputeTargetHttpProxyCreationTimestamp(v interface{}) interface{} {
return v
}
func flattenComputeTargetHttpProxyDescription(v interface{}) interface{} {
return v
}
func flattenComputeTargetHttpProxyProxyId(v interface{}) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := strconv.Atoi(strVal); err == nil {
return intVal
} // let terraform core handle it if we can't convert the string to an int.
}
return v
}
func flattenComputeTargetHttpProxyName(v interface{}) interface{} {
return v
}
func flattenComputeTargetHttpProxyUrlMap(v interface{}) interface{} {
return v
}
func expandComputeTargetHttpProxyDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeTargetHttpProxyName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeTargetHttpProxyUrlMap(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
f, err := parseGlobalFieldValue("urlMaps", v.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for url_map: %s", err)
}
return f.RelativeLink(), nil
}

View File

@ -1,37 +1,53 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google package google
import ( import (
"fmt" "fmt"
"log" "log"
"strconv" "strconv"
"time"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/compute/v1" compute "google.golang.org/api/compute/v1"
)
const (
canonicalSslCertificateTemplate = "https://www.googleapis.com/compute/v1/projects/%s/global/sslCertificates/%s"
) )
func resourceComputeTargetHttpsProxy() *schema.Resource { func resourceComputeTargetHttpsProxy() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeTargetHttpsProxyCreate, Create: resourceComputeTargetHttpsProxyCreate,
Read: resourceComputeTargetHttpsProxyRead, Read: resourceComputeTargetHttpsProxyRead,
Delete: resourceComputeTargetHttpsProxyDelete,
Update: resourceComputeTargetHttpsProxyUpdate, Update: resourceComputeTargetHttpsProxyUpdate,
Delete: resourceComputeTargetHttpsProxyDelete,
Importer: &schema.ResourceImporter{ Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough, State: resourceComputeTargetHttpsProxyImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Update: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
}, },
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"ssl_certificates": {
"ssl_certificates": &schema.Schema{
Type: schema.TypeList, Type: schema.TypeList,
Required: true, Required: true,
Elem: &schema.Schema{ Elem: &schema.Schema{
@ -39,35 +55,34 @@ func resourceComputeTargetHttpsProxy() *schema.Resource {
DiffSuppressFunc: compareSelfLinkOrResourceName, DiffSuppressFunc: compareSelfLinkOrResourceName,
}, },
}, },
"url_map": {
"url_map": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
DiffSuppressFunc: compareSelfLinkRelativePaths, DiffSuppressFunc: compareSelfLinkOrResourceName,
}, },
"description": {
"description": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"creation_timestamp": {
"self_link": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"proxy_id": {
"proxy_id": &schema.Schema{ Type: schema.TypeInt,
Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"project": {
"project": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"self_link": {
Type: schema.TypeString,
Computed: true,
},
}, },
} }
} }
@ -80,89 +95,64 @@ func resourceComputeTargetHttpsProxyCreate(d *schema.ResourceData, meta interfac
return err return err
} }
sslCertificates, err := expandSslCertificates(d, config) descriptionProp, err := expandComputeTargetHttpsProxyDescription(d.Get("description"), d, config)
if err != nil {
return err
}
nameProp, err := expandComputeTargetHttpsProxyName(d.Get("name"), d, config)
if err != nil {
return err
}
sslCertificatesProp, err := expandComputeTargetHttpsProxySslCertificates(d.Get("ssl_certificates"), d, config)
if err != nil {
return err
}
urlMapProp, err := expandComputeTargetHttpsProxyUrlMap(d.Get("url_map"), d, config)
if err != nil { if err != nil {
return err return err
} }
proxy := &compute.TargetHttpsProxy{ obj := map[string]interface{}{
Name: d.Get("name").(string), "description": descriptionProp,
UrlMap: d.Get("url_map").(string), "name": nameProp,
SslCertificates: sslCertificates, "sslCertificates": sslCertificatesProp,
"urlMap": urlMapProp,
} }
if v, ok := d.GetOk("description"); ok { url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetHttpsProxies")
proxy.Description = v.(string) if err != nil {
return err
} }
log.Printf("[DEBUG] TargetHttpsProxy insert request: %#v", proxy) log.Printf("[DEBUG] Creating new TargetHttpsProxy: %#v", obj)
op, err := config.clientCompute.TargetHttpsProxies.Insert( res, err := Post(config, url, obj)
project, proxy).Do()
if err != nil { if err != nil {
return fmt.Errorf("Error creating TargetHttpsProxy: %s", err) return fmt.Errorf("Error creating TargetHttpsProxy: %s", err)
} }
err = computeOperationWait(config.clientCompute, op, project, "Creating Target Https Proxy") // Store the ID now
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
op := &compute.Operation{}
err = Convert(res, op)
if err != nil { if err != nil {
return err return err
} }
d.SetId(proxy.Name) waitErr := computeOperationWaitTime(
config.clientCompute, op, project, "Creating TargetHttpsProxy",
int(d.Timeout(schema.TimeoutCreate).Minutes()))
return resourceComputeTargetHttpsProxyRead(d, meta) if waitErr != nil {
} // The resource didn't actually create
d.SetId("")
func resourceComputeTargetHttpsProxyUpdate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error waiting to create TargetHttpsProxy: %s", waitErr)
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
} }
d.Partial(true)
if d.HasChange("url_map") {
url_map := d.Get("url_map").(string)
url_map_ref := &compute.UrlMapReference{UrlMap: url_map}
op, err := config.clientCompute.TargetHttpsProxies.SetUrlMap(
project, d.Id(), url_map_ref).Do()
if err != nil {
return fmt.Errorf("Error updating Target HTTPS proxy URL map: %s", err)
}
err = computeOperationWait(config.clientCompute, op, project, "Updating Target Https Proxy URL Map")
if err != nil {
return err
}
d.SetPartial("url_map")
}
if d.HasChange("ssl_certificates") {
certs, err := expandSslCertificates(d, config)
if err != nil {
return err
}
cert_ref := &compute.TargetHttpsProxiesSetSslCertificatesRequest{
SslCertificates: certs,
}
op, err := config.clientCompute.TargetHttpsProxies.SetSslCertificates(
project, d.Id(), cert_ref).Do()
if err != nil {
return fmt.Errorf("Error updating Target Https Proxy SSL Certificates: %s", err)
}
err = computeOperationWait(config.clientCompute, op, project, "Updating Target Https Proxy SSL certificates")
if err != nil {
return err
}
d.SetPartial("ssl_certificate")
}
d.Partial(false)
return resourceComputeTargetHttpsProxyRead(d, meta) return resourceComputeTargetHttpsProxyRead(d, meta)
} }
@ -174,23 +164,129 @@ func resourceComputeTargetHttpsProxyRead(d *schema.ResourceData, meta interface{
return err return err
} }
proxy, err := config.clientCompute.TargetHttpsProxies.Get( url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetHttpsProxies/{{name}}")
project, d.Id()).Do()
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Target HTTPS proxy %q", d.Get("name").(string))) return err
} }
d.Set("ssl_certificates", proxy.SslCertificates) res, err := Get(config, url)
d.Set("proxy_id", strconv.FormatUint(proxy.Id, 10)) if err != nil {
d.Set("self_link", proxy.SelfLink) return handleNotFoundError(err, d, fmt.Sprintf("ComputeTargetHttpsProxy %q", d.Id()))
d.Set("description", proxy.Description) }
d.Set("url_map", proxy.UrlMap) if err := d.Set("creation_timestamp", flattenComputeTargetHttpsProxyCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("name", proxy.Name) return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
d.Set("project", project) }
if err := d.Set("description", flattenComputeTargetHttpsProxyDescription(res["description"])); err != nil {
return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
}
if err := d.Set("proxy_id", flattenComputeTargetHttpsProxyProxyId(res["id"])); err != nil {
return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
}
if err := d.Set("name", flattenComputeTargetHttpsProxyName(res["name"])); err != nil {
return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
}
if err := d.Set("ssl_certificates", flattenComputeTargetHttpsProxySslCertificates(res["sslCertificates"])); err != nil {
return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
}
if err := d.Set("url_map", flattenComputeTargetHttpsProxyUrlMap(res["urlMap"])); err != nil {
return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading TargetHttpsProxy: %s", err)
}
return nil return nil
} }
func resourceComputeTargetHttpsProxyUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
}
var url string
var res map[string]interface{}
op := &compute.Operation{}
d.Partial(true)
if d.HasChange("ssl_certificates") {
sslCertificatesProp, err := expandComputeTargetHttpsProxySslCertificates(d.Get("ssl_certificates"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{
"sslCertificates": sslCertificatesProp,
}
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/targetHttpsProxies/{{name}}/setSslCertificates")
if err != nil {
return err
}
res, err = sendRequest(config, "POST", url, obj)
if err != nil {
return fmt.Errorf("Error updating TargetHttpsProxy %q: %s", d.Id(), err)
}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Updating TargetHttpsProxy",
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
if err != nil {
return err
}
d.SetPartial("ssl_certificates")
}
if d.HasChange("url_map") {
urlMapProp, err := expandComputeTargetHttpsProxyUrlMap(d.Get("url_map"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{
"urlMap": urlMapProp,
}
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/targetHttpsProxies/{{name}}/setUrlMap")
if err != nil {
return err
}
res, err = sendRequest(config, "POST", url, obj)
if err != nil {
return fmt.Errorf("Error updating TargetHttpsProxy %q: %s", d.Id(), err)
}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Updating TargetHttpsProxy",
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
if err != nil {
return err
}
d.SetPartial("url_map")
}
d.Partial(false)
return resourceComputeTargetHttpsProxyRead(d, meta)
}
func resourceComputeTargetHttpsProxyDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeTargetHttpsProxyDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
@ -199,35 +295,103 @@ func resourceComputeTargetHttpsProxyDelete(d *schema.ResourceData, meta interfac
return err return err
} }
// Delete the TargetHttpsProxy url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetHttpsProxies/{{name}}")
log.Printf("[DEBUG] TargetHttpsProxy delete request") if err != nil {
op, err := config.clientCompute.TargetHttpsProxies.Delete( return err
project, d.Id()).Do() }
if err != nil {
return fmt.Errorf("Error deleting TargetHttpsProxy: %s", err) log.Printf("[DEBUG] Deleting TargetHttpsProxy %q", d.Id())
} res, err := Delete(config, url)
if err != nil {
err = computeOperationWait(config.clientCompute, op, project, "Deleting Target Https Proxy") return fmt.Errorf("Error deleting TargetHttpsProxy %q: %s", d.Id(), err)
}
op := &compute.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Deleting TargetHttpsProxy",
int(d.Timeout(schema.TimeoutDelete).Minutes()))
if err != nil { if err != nil {
return err return err
} }
d.SetId("")
return nil return nil
} }
func expandSslCertificates(d *schema.ResourceData, config *Config) ([]string, error) { func resourceComputeTargetHttpsProxyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
configured := d.Get("ssl_certificates").([]interface{}) config := meta.(*Config)
certs := make([]string, 0, len(configured)) parseImportId([]string{"projects/(?P<project>[^/]+)/global/targetHttpsProxies/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config)
for _, sslCertificate := range configured { // Replace import id for the resource id
sslCertificateFieldValue, err := ParseSslCertificateFieldValue(sslCertificate.(string), d, config) id, err := replaceVars(d, config, "{{name}}")
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid ssl certificate: %s", err) return nil, fmt.Errorf("Error constructing id: %s", err)
}
certs = append(certs, sslCertificateFieldValue.RelativeLink())
} }
d.SetId(id)
return certs, nil return []*schema.ResourceData{d}, nil
}
func flattenComputeTargetHttpsProxyCreationTimestamp(v interface{}) interface{} {
return v
}
func flattenComputeTargetHttpsProxyDescription(v interface{}) interface{} {
return v
}
func flattenComputeTargetHttpsProxyProxyId(v interface{}) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := strconv.Atoi(strVal); err == nil {
return intVal
} // let terraform core handle it if we can't convert the string to an int.
}
return v
}
func flattenComputeTargetHttpsProxyName(v interface{}) interface{} {
return v
}
func flattenComputeTargetHttpsProxySslCertificates(v interface{}) interface{} {
return v
}
func flattenComputeTargetHttpsProxyUrlMap(v interface{}) interface{} {
return v
}
func expandComputeTargetHttpsProxyDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeTargetHttpsProxyName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeTargetHttpsProxySslCertificates(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
f, err := parseGlobalFieldValue("sslCertificates", raw.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for ssl_certificates: %s", err)
}
req = append(req, f.RelativeLink())
}
return req, nil
}
func expandComputeTargetHttpsProxyUrlMap(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
f, err := parseGlobalFieldValue("urlMaps", v.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for url_map: %s", err)
}
return f.RelativeLink(), nil
} }

View File

@ -10,6 +10,10 @@ import (
"google.golang.org/api/compute/v1" "google.golang.org/api/compute/v1"
) )
const (
canonicalSslCertificateTemplate = "https://www.googleapis.com/compute/v1/projects/%s/global/sslCertificates/%s"
)
func TestAccComputeTargetHttpsProxy_basic(t *testing.T) { func TestAccComputeTargetHttpsProxy_basic(t *testing.T) {
t.Parallel() t.Parallel()

View File

@ -21,6 +21,7 @@ import (
"time" "time"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
compute "google.golang.org/api/compute/v1" compute "google.golang.org/api/compute/v1"
) )
@ -67,9 +68,10 @@ func resourceComputeTargetSslProxy() *schema.Resource {
ForceNew: true, ForceNew: true,
}, },
"proxy_header": { "proxy_header": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Default: "NONE", ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false),
Default: "NONE",
}, },
"creation_timestamp": { "creation_timestamp": {
Type: schema.TypeString, Type: schema.TypeString,
@ -161,7 +163,7 @@ func resourceComputeTargetSslProxyCreate(d *schema.ResourceData, meta interface{
if waitErr != nil { if waitErr != nil {
// The resource didn't actually create // The resource didn't actually create
d.SetId("") d.SetId("")
return waitErr return fmt.Errorf("Error waiting to create TargetSslProxy: %s", waitErr)
} }
return resourceComputeTargetSslProxyRead(d, meta) return resourceComputeTargetSslProxyRead(d, meta)
@ -184,16 +186,33 @@ func resourceComputeTargetSslProxyRead(d *schema.ResourceData, meta interface{})
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("ComputeTargetSslProxy %q", d.Id())) return handleNotFoundError(err, d, fmt.Sprintf("ComputeTargetSslProxy %q", d.Id()))
} }
if err := d.Set("creation_timestamp", flattenComputeTargetSslProxyCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("creation_timestamp", flattenComputeTargetSslProxyCreationTimestamp(res["creationTimestamp"])) return fmt.Errorf("Error reading TargetSslProxy: %s", err)
d.Set("description", flattenComputeTargetSslProxyDescription(res["description"])) }
d.Set("proxy_id", flattenComputeTargetSslProxyProxyId(res["id"])) if err := d.Set("description", flattenComputeTargetSslProxyDescription(res["description"])); err != nil {
d.Set("name", flattenComputeTargetSslProxyName(res["name"])) return fmt.Errorf("Error reading TargetSslProxy: %s", err)
d.Set("proxy_header", flattenComputeTargetSslProxyProxyHeader(res["proxyHeader"])) }
d.Set("backend_service", flattenComputeTargetSslProxyBackendService(res["service"])) if err := d.Set("proxy_id", flattenComputeTargetSslProxyProxyId(res["id"])); err != nil {
d.Set("ssl_certificates", flattenComputeTargetSslProxySslCertificates(res["sslCertificates"])) return fmt.Errorf("Error reading TargetSslProxy: %s", err)
d.Set("self_link", res["selfLink"]) }
d.Set("project", project) if err := d.Set("name", flattenComputeTargetSslProxyName(res["name"])); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
if err := d.Set("proxy_header", flattenComputeTargetSslProxyProxyHeader(res["proxyHeader"])); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
if err := d.Set("backend_service", flattenComputeTargetSslProxyBackendService(res["service"])); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
if err := d.Set("ssl_certificates", flattenComputeTargetSslProxySslCertificates(res["sslCertificates"])); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
return nil return nil
} }
@ -210,34 +229,16 @@ func resourceComputeTargetSslProxyUpdate(d *schema.ResourceData, meta interface{
var res map[string]interface{} var res map[string]interface{}
op := &compute.Operation{} op := &compute.Operation{}
d.Partial(true)
if d.HasChange("proxy_header") { if d.HasChange("proxy_header") {
descriptionProp, err := expandComputeTargetSslProxyDescription(d.Get("description"), d, config)
if err != nil {
return err
}
nameProp, err := expandComputeTargetSslProxyName(d.Get("name"), d, config)
if err != nil {
return err
}
proxyHeaderProp, err := expandComputeTargetSslProxyProxyHeader(d.Get("proxy_header"), d, config) proxyHeaderProp, err := expandComputeTargetSslProxyProxyHeader(d.Get("proxy_header"), d, config)
if err != nil { if err != nil {
return err return err
} }
serviceProp, err := expandComputeTargetSslProxyBackendService(d.Get("backend_service"), d, config)
if err != nil {
return err
}
sslCertificatesProp, err := expandComputeTargetSslProxySslCertificates(d.Get("ssl_certificates"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{ obj := map[string]interface{}{
"description": descriptionProp, "proxyHeader": proxyHeaderProp,
"name": nameProp,
"proxyHeader": proxyHeaderProp,
"service": serviceProp,
"sslCertificates": sslCertificatesProp,
} }
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetSslProxies/{{name}}/setProxyHeader") url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetSslProxies/{{name}}/setProxyHeader")
if err != nil { if err != nil {
@ -260,35 +261,17 @@ func resourceComputeTargetSslProxyUpdate(d *schema.ResourceData, meta interface{
if err != nil { if err != nil {
return err return err
} }
d.SetPartial("proxy_header")
} }
if d.HasChange("backend_service") { if d.HasChange("backend_service") {
descriptionProp, err := expandComputeTargetSslProxyDescription(d.Get("description"), d, config)
if err != nil {
return err
}
nameProp, err := expandComputeTargetSslProxyName(d.Get("name"), d, config)
if err != nil {
return err
}
proxyHeaderProp, err := expandComputeTargetSslProxyProxyHeader(d.Get("proxy_header"), d, config)
if err != nil {
return err
}
serviceProp, err := expandComputeTargetSslProxyBackendService(d.Get("backend_service"), d, config) serviceProp, err := expandComputeTargetSslProxyBackendService(d.Get("backend_service"), d, config)
if err != nil { if err != nil {
return err return err
} }
sslCertificatesProp, err := expandComputeTargetSslProxySslCertificates(d.Get("ssl_certificates"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{ obj := map[string]interface{}{
"description": descriptionProp, "service": serviceProp,
"name": nameProp,
"proxyHeader": proxyHeaderProp,
"service": serviceProp,
"sslCertificates": sslCertificatesProp,
} }
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetSslProxies/{{name}}/setBackendService") url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetSslProxies/{{name}}/setBackendService")
if err != nil { if err != nil {
@ -311,34 +294,16 @@ func resourceComputeTargetSslProxyUpdate(d *schema.ResourceData, meta interface{
if err != nil { if err != nil {
return err return err
} }
d.SetPartial("backend_service")
} }
if d.HasChange("ssl_certificates") { if d.HasChange("ssl_certificates") {
descriptionProp, err := expandComputeTargetSslProxyDescription(d.Get("description"), d, config)
if err != nil {
return err
}
nameProp, err := expandComputeTargetSslProxyName(d.Get("name"), d, config)
if err != nil {
return err
}
proxyHeaderProp, err := expandComputeTargetSslProxyProxyHeader(d.Get("proxy_header"), d, config)
if err != nil {
return err
}
serviceProp, err := expandComputeTargetSslProxyBackendService(d.Get("backend_service"), d, config)
if err != nil {
return err
}
sslCertificatesProp, err := expandComputeTargetSslProxySslCertificates(d.Get("ssl_certificates"), d, config) sslCertificatesProp, err := expandComputeTargetSslProxySslCertificates(d.Get("ssl_certificates"), d, config)
if err != nil { if err != nil {
return err return err
} }
obj := map[string]interface{}{ obj := map[string]interface{}{
"description": descriptionProp,
"name": nameProp,
"proxyHeader": proxyHeaderProp,
"service": serviceProp,
"sslCertificates": sslCertificatesProp, "sslCertificates": sslCertificatesProp,
} }
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetSslProxies/{{name}}/setSslCertificates") url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetSslProxies/{{name}}/setSslCertificates")
@ -362,8 +327,12 @@ func resourceComputeTargetSslProxyUpdate(d *schema.ResourceData, meta interface{
if err != nil { if err != nil {
return err return err
} }
d.SetPartial("ssl_certificates")
} }
d.Partial(false)
return resourceComputeTargetSslProxyRead(d, meta) return resourceComputeTargetSslProxyRead(d, meta)
} }

View File

@ -1,62 +1,84 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google package google
import ( import (
"fmt" "fmt"
"log" "log"
"strconv" "strconv"
"time"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/compute/v1" "github.com/hashicorp/terraform/helper/validation"
compute "google.golang.org/api/compute/v1"
) )
func resourceComputeTargetTcpProxy() *schema.Resource { func resourceComputeTargetTcpProxy() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeTargetTcpProxyCreate, Create: resourceComputeTargetTcpProxyCreate,
Read: resourceComputeTargetTcpProxyRead, Read: resourceComputeTargetTcpProxyRead,
Delete: resourceComputeTargetTcpProxyDelete,
Update: resourceComputeTargetTcpProxyUpdate, Update: resourceComputeTargetTcpProxyUpdate,
Delete: resourceComputeTargetTcpProxyDelete,
Importer: &schema.ResourceImporter{ Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough, State: resourceComputeTargetTcpProxyImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Update: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
}, },
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "backend_service": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
"name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"description": {
"backend_service": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"proxy_header": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "NONE",
},
"description": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"proxy_header": {
"proxy_id": &schema.Schema{ Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false),
Default: "NONE",
},
"creation_timestamp": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"proxy_id": {
"project": &schema.Schema{ Type: schema.TypeInt,
Computed: true,
},
"project": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"self_link": {
"self_link": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
@ -72,61 +94,64 @@ func resourceComputeTargetTcpProxyCreate(d *schema.ResourceData, meta interface{
return err return err
} }
proxy := &compute.TargetTcpProxy{ descriptionProp, err := expandComputeTargetTcpProxyDescription(d.Get("description"), d, config)
Name: d.Get("name").(string), if err != nil {
Service: d.Get("backend_service").(string), return err
ProxyHeader: d.Get("proxy_header").(string), }
Description: d.Get("description").(string), nameProp, err := expandComputeTargetTcpProxyName(d.Get("name"), d, config)
if err != nil {
return err
}
proxyHeaderProp, err := expandComputeTargetTcpProxyProxyHeader(d.Get("proxy_header"), d, config)
if err != nil {
return err
}
serviceProp, err := expandComputeTargetTcpProxyBackendService(d.Get("backend_service"), d, config)
if err != nil {
return err
} }
log.Printf("[DEBUG] TargetTcpProxy insert request: %#v", proxy) obj := map[string]interface{}{
op, err := config.clientCompute.TargetTcpProxies.Insert( "description": descriptionProp,
project, proxy).Do() "name": nameProp,
"proxyHeader": proxyHeaderProp,
"service": serviceProp,
}
url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetTcpProxies")
if err != nil {
return err
}
log.Printf("[DEBUG] Creating new TargetTcpProxy: %#v", obj)
res, err := Post(config, url, obj)
if err != nil { if err != nil {
return fmt.Errorf("Error creating TargetTcpProxy: %s", err) return fmt.Errorf("Error creating TargetTcpProxy: %s", err)
} }
err = computeOperationWait(config.clientCompute, op, project, "Creating Target Tcp Proxy") // Store the ID now
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
op := &compute.Operation{}
err = Convert(res, op)
if err != nil { if err != nil {
return err return err
} }
d.SetId(proxy.Name) waitErr := computeOperationWaitTime(
config.clientCompute, op, project, "Creating TargetTcpProxy",
int(d.Timeout(schema.TimeoutCreate).Minutes()))
return resourceComputeTargetTcpProxyRead(d, meta) if waitErr != nil {
} // The resource didn't actually create
d.SetId("")
func resourceComputeTargetTcpProxyUpdate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error waiting to create TargetTcpProxy: %s", waitErr)
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
} }
d.Partial(true)
if d.HasChange("proxy_header") {
proxy_header := d.Get("proxy_header").(string)
proxy_header_payload := &compute.TargetTcpProxiesSetProxyHeaderRequest{
ProxyHeader: proxy_header,
}
op, err := config.clientCompute.TargetTcpProxies.SetProxyHeader(
project, d.Id(), proxy_header_payload).Do()
if err != nil {
return fmt.Errorf("Error updating target: %s", err)
}
err = computeOperationWait(config.clientCompute, op, project, "Updating Target Tcp Proxy")
if err != nil {
return err
}
d.SetPartial("proxy_header")
}
d.Partial(false)
return resourceComputeTargetTcpProxyRead(d, meta) return resourceComputeTargetTcpProxyRead(d, meta)
} }
@ -138,23 +163,129 @@ func resourceComputeTargetTcpProxyRead(d *schema.ResourceData, meta interface{})
return err return err
} }
proxy, err := config.clientCompute.TargetTcpProxies.Get( url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetTcpProxies/{{name}}")
project, d.Id()).Do()
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Target TCP Proxy %q", d.Get("name").(string))) return err
} }
d.Set("name", proxy.Name) res, err := Get(config, url)
d.Set("backend_service", proxy.Service) if err != nil {
d.Set("proxy_header", proxy.ProxyHeader) return handleNotFoundError(err, d, fmt.Sprintf("ComputeTargetTcpProxy %q", d.Id()))
d.Set("description", proxy.Description) }
d.Set("project", project) if err := d.Set("creation_timestamp", flattenComputeTargetTcpProxyCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("self_link", proxy.SelfLink) return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
d.Set("proxy_id", strconv.FormatUint(proxy.Id, 10)) }
if err := d.Set("description", flattenComputeTargetTcpProxyDescription(res["description"])); err != nil {
return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
}
if err := d.Set("proxy_id", flattenComputeTargetTcpProxyProxyId(res["id"])); err != nil {
return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
}
if err := d.Set("name", flattenComputeTargetTcpProxyName(res["name"])); err != nil {
return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
}
if err := d.Set("proxy_header", flattenComputeTargetTcpProxyProxyHeader(res["proxyHeader"])); err != nil {
return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
}
if err := d.Set("backend_service", flattenComputeTargetTcpProxyBackendService(res["service"])); err != nil {
return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading TargetTcpProxy: %s", err)
}
return nil return nil
} }
func resourceComputeTargetTcpProxyUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
}
var url string
var res map[string]interface{}
op := &compute.Operation{}
d.Partial(true)
if d.HasChange("proxy_header") {
proxyHeaderProp, err := expandComputeTargetTcpProxyProxyHeader(d.Get("proxy_header"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{
"proxyHeader": proxyHeaderProp,
}
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetTcpProxies/{{name}}/setProxyHeader")
if err != nil {
return err
}
res, err = sendRequest(config, "POST", url, obj)
if err != nil {
return fmt.Errorf("Error updating TargetTcpProxy %q: %s", d.Id(), err)
}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Updating TargetTcpProxy",
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
if err != nil {
return err
}
d.SetPartial("proxy_header")
}
if d.HasChange("backend_service") {
serviceProp, err := expandComputeTargetTcpProxyBackendService(d.Get("backend_service"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{
"service": serviceProp,
}
url, err = replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetTcpProxies/{{name}}/setBackendService")
if err != nil {
return err
}
res, err = sendRequest(config, "POST", url, obj)
if err != nil {
return fmt.Errorf("Error updating TargetTcpProxy %q: %s", d.Id(), err)
}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Updating TargetTcpProxy",
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
if err != nil {
return err
}
d.SetPartial("backend_service")
}
d.Partial(false)
return resourceComputeTargetTcpProxyRead(d, meta)
}
func resourceComputeTargetTcpProxyDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeTargetTcpProxyDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
@ -163,19 +294,94 @@ func resourceComputeTargetTcpProxyDelete(d *schema.ResourceData, meta interface{
return err return err
} }
// Delete the TargetTcpProxy url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/targetTcpProxies/{{name}}")
log.Printf("[DEBUG] TargetTcpProxy delete request") if err != nil {
op, err := config.clientCompute.TargetTcpProxies.Delete( return err
project, d.Id()).Do() }
if err != nil {
return fmt.Errorf("Error deleting TargetTcpProxy: %s", err) log.Printf("[DEBUG] Deleting TargetTcpProxy %q", d.Id())
} res, err := Delete(config, url)
if err != nil {
err = computeOperationWait(config.clientCompute, op, project, "Deleting Target Tcp Proxy") return fmt.Errorf("Error deleting TargetTcpProxy %q: %s", d.Id(), err)
}
op := &compute.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Deleting TargetTcpProxy",
int(d.Timeout(schema.TimeoutDelete).Minutes()))
if err != nil { if err != nil {
return err return err
} }
d.SetId("")
return nil return nil
} }
func resourceComputeTargetTcpProxyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
parseImportId([]string{"projects/(?P<project>[^/]+)/global/targetTcpProxies/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config)
// Replace import id for the resource id
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenComputeTargetTcpProxyCreationTimestamp(v interface{}) interface{} {
return v
}
func flattenComputeTargetTcpProxyDescription(v interface{}) interface{} {
return v
}
func flattenComputeTargetTcpProxyProxyId(v interface{}) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := strconv.Atoi(strVal); err == nil {
return intVal
} // let terraform core handle it if we can't convert the string to an int.
}
return v
}
func flattenComputeTargetTcpProxyName(v interface{}) interface{} {
return v
}
func flattenComputeTargetTcpProxyProxyHeader(v interface{}) interface{} {
return v
}
func flattenComputeTargetTcpProxyBackendService(v interface{}) interface{} {
return v
}
func expandComputeTargetTcpProxyDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeTargetTcpProxyName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeTargetTcpProxyProxyHeader(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeTargetTcpProxyBackendService(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
f, err := parseGlobalFieldValue("backendServices", v.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for backend_service: %s", err)
}
return f.RelativeLink(), nil
}

View File

@ -1,56 +1,79 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google package google
import ( import (
"fmt" "fmt"
"log"
"time"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
compute "google.golang.org/api/compute/v1"
"google.golang.org/api/compute/v1"
) )
func resourceComputeVpnGateway() *schema.Resource { func resourceComputeVpnGateway() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
// Unfortunately, the VPNGatewayService does not support update
// operations. This is why everything is marked forcenew
Create: resourceComputeVpnGatewayCreate, Create: resourceComputeVpnGatewayCreate,
Read: resourceComputeVpnGatewayRead, Read: resourceComputeVpnGatewayRead,
Delete: resourceComputeVpnGatewayDelete, Delete: resourceComputeVpnGatewayDelete,
Importer: &schema.ResourceImporter{
State: resourceComputeVpnGatewayImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
},
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"network": {
"network": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
DiffSuppressFunc: compareSelfLinkOrResourceName, DiffSuppressFunc: compareSelfLinkOrResourceName,
}, },
"description": {
"description": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"region": {
"project": &schema.Schema{ Type: schema.TypeString,
Computed: true,
Optional: true,
ForceNew: true,
DiffSuppressFunc: compareSelfLinkOrResourceName,
StateFunc: NameFromSelfLinkStateFunc,
},
"creation_timestamp": {
Type: schema.TypeString,
Computed: true,
},
"project": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"self_link": {
"region": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"self_link": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
@ -60,42 +83,68 @@ func resourceComputeVpnGateway() *schema.Resource {
func resourceComputeVpnGatewayCreate(d *schema.ResourceData, meta interface{}) error { func resourceComputeVpnGatewayCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
network, err := ParseNetworkFieldValue(d.Get("network").(string), d, config)
if err != nil {
return err
}
region, err := getRegion(d, config)
if err != nil {
return err
}
project, err := getProject(d, config) project, err := getProject(d, config)
if err != nil { if err != nil {
return err return err
} }
name := d.Get("name").(string) descriptionProp, err := expandComputeVpnGatewayDescription(d.Get("description"), d, config)
vpnGatewaysService := compute.NewTargetVpnGatewaysService(config.clientCompute)
vpnGateway := &compute.TargetVpnGateway{
Name: name,
Network: network.RelativeLink(),
}
if v, ok := d.GetOk("description"); ok {
vpnGateway.Description = v.(string)
}
op, err := vpnGatewaysService.Insert(project, region, vpnGateway).Do()
if err != nil { if err != nil {
return fmt.Errorf("Error Inserting VPN Gateway %s into network %s: %s", name, network.Name, err) return err
}
nameProp, err := expandComputeVpnGatewayName(d.Get("name"), d, config)
if err != nil {
return err
}
networkProp, err := expandComputeVpnGatewayNetwork(d.Get("network"), d, config)
if err != nil {
return err
}
regionProp, err := expandComputeVpnGatewayRegion(d.Get("region"), d, config)
if err != nil {
return err
} }
err = computeOperationWait(config.clientCompute, op, project, "Inserting VPN Gateway") obj := map[string]interface{}{
"description": descriptionProp,
"name": nameProp,
"network": networkProp,
"region": regionProp,
}
url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/targetVpnGateways")
if err != nil { if err != nil {
return fmt.Errorf("Error Waiting to Insert VPN Gateway %s into network %s: %s", name, network.Name, err) return err
}
log.Printf("[DEBUG] Creating new VpnGateway: %#v", obj)
res, err := Post(config, url, obj)
if err != nil {
return fmt.Errorf("Error creating VpnGateway: %s", err)
}
// Store the ID now
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
op := &compute.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
waitErr := computeOperationWaitTime(
config.clientCompute, op, project, "Creating VpnGateway",
int(d.Timeout(schema.TimeoutCreate).Minutes()))
if waitErr != nil {
// The resource didn't actually create
d.SetId("")
return fmt.Errorf("Error waiting to create VpnGateway: %s", waitErr)
} }
return resourceComputeVpnGatewayRead(d, meta) return resourceComputeVpnGatewayRead(d, meta)
@ -104,32 +153,41 @@ func resourceComputeVpnGatewayCreate(d *schema.ResourceData, meta interface{}) e
func resourceComputeVpnGatewayRead(d *schema.ResourceData, meta interface{}) error { func resourceComputeVpnGatewayRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
region, err := getRegion(d, config)
if err != nil {
return err
}
project, err := getProject(d, config) project, err := getProject(d, config)
if err != nil { if err != nil {
return err return err
} }
name := d.Get("name").(string) url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/targetVpnGateways/{{name}}")
vpnGatewaysService := compute.NewTargetVpnGatewaysService(config.clientCompute)
vpnGateway, err := vpnGatewaysService.Get(project, region, name).Do()
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("VPN Gateway %q", d.Get("name").(string))) return err
} }
d.Set("name", vpnGateway.Name) res, err := Get(config, url)
d.Set("description", vpnGateway.Description) if err != nil {
d.Set("network", vpnGateway.Network) return handleNotFoundError(err, d, fmt.Sprintf("ComputeVpnGateway %q", d.Id()))
d.Set("project", project) }
d.Set("region", region) if err := d.Set("creation_timestamp", flattenComputeVpnGatewayCreationTimestamp(res["creationTimestamp"])); err != nil {
d.Set("self_link", vpnGateway.SelfLink) return fmt.Errorf("Error reading VpnGateway: %s", err)
d.SetId(name) }
if err := d.Set("description", flattenComputeVpnGatewayDescription(res["description"])); err != nil {
return fmt.Errorf("Error reading VpnGateway: %s", err)
}
if err := d.Set("name", flattenComputeVpnGatewayName(res["name"])); err != nil {
return fmt.Errorf("Error reading VpnGateway: %s", err)
}
if err := d.Set("network", flattenComputeVpnGatewayNetwork(res["network"])); err != nil {
return fmt.Errorf("Error reading VpnGateway: %s", err)
}
if err := d.Set("region", flattenComputeVpnGatewayRegion(res["region"])); err != nil {
return fmt.Errorf("Error reading VpnGateway: %s", err)
}
if err := d.Set("self_link", res["selfLink"]); err != nil {
return fmt.Errorf("Error reading VpnGateway: %s", err)
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading VpnGateway: %s", err)
}
return nil return nil
} }
@ -137,29 +195,93 @@ func resourceComputeVpnGatewayRead(d *schema.ResourceData, meta interface{}) err
func resourceComputeVpnGatewayDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeVpnGatewayDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
region, err := getRegion(d, config)
if err != nil {
return err
}
project, err := getProject(d, config) project, err := getProject(d, config)
if err != nil { if err != nil {
return err return err
} }
name := d.Get("name").(string) url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/targetVpnGateways/{{name}}")
vpnGatewaysService := compute.NewTargetVpnGatewaysService(config.clientCompute)
op, err := vpnGatewaysService.Delete(project, region, name).Do()
if err != nil { if err != nil {
return fmt.Errorf("Error Reading VPN Gateway %s: %s", name, err) return err
} }
err = computeOperationWait(config.clientCompute, op, project, "Deleting VPN Gateway") log.Printf("[DEBUG] Deleting VpnGateway %q", d.Id())
res, err := Delete(config, url)
if err != nil { if err != nil {
return fmt.Errorf("Error Waiting to Delete VPN Gateway %s: %s", name, err) return fmt.Errorf("Error deleting VpnGateway %q: %s", d.Id(), err)
}
op := &compute.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
err = computeOperationWaitTime(
config.clientCompute, op, project, "Deleting VpnGateway",
int(d.Timeout(schema.TimeoutDelete).Minutes()))
if err != nil {
return err
} }
return nil return nil
} }
func resourceComputeVpnGatewayImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
parseImportId([]string{"projects/(?P<project>[^/]+)/regions/(?P<region>[^/]+)/targetVpnGateways/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<region>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config)
// Replace import id for the resource id
id, err := replaceVars(d, config, "{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenComputeVpnGatewayCreationTimestamp(v interface{}) interface{} {
return v
}
func flattenComputeVpnGatewayDescription(v interface{}) interface{} {
return v
}
func flattenComputeVpnGatewayName(v interface{}) interface{} {
return v
}
func flattenComputeVpnGatewayNetwork(v interface{}) interface{} {
return v
}
func flattenComputeVpnGatewayRegion(v interface{}) interface{} {
return v
}
func expandComputeVpnGatewayDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeVpnGatewayName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandComputeVpnGatewayNetwork(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
f, err := parseGlobalFieldValue("networks", v.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for network: %s", err)
}
return f.RelativeLink(), nil
}
func expandComputeVpnGatewayRegion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for region: %s", err)
}
return f.RelativeLink(), nil
}

View File

@ -282,6 +282,24 @@ func resourceContainerCluster() *schema.Resource {
ForceNew: true, ForceNew: true,
}, },
"client_certificate_config": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
DiffSuppressFunc: masterAuthClientCertCfgSuppress,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"issue_client_certificate": {
Type: schema.TypeBool,
Required: true,
ForceNew: true,
DiffSuppressFunc: masterAuthClientCertCfgSuppress,
},
},
},
},
"client_certificate": { "client_certificate": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
@ -490,6 +508,15 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
Password: masterAuth["password"].(string), Password: masterAuth["password"].(string),
Username: masterAuth["username"].(string), Username: masterAuth["username"].(string),
} }
if certConfigV, ok := masterAuth["client_certificate_config"]; ok {
certConfigs := certConfigV.([]interface{})
if len(certConfigs) > 0 {
certConfig := certConfigs[0].(map[string]interface{})
cluster.MasterAuth.ClientCertificateConfig = &containerBeta.ClientCertificateConfig{
IssueClientCertificate: certConfig["issue_client_certificate"].(bool),
}
}
}
} }
if v, ok := d.GetOk("master_authorized_networks_config"); ok { if v, ok := d.GetOk("master_authorized_networks_config"); ok {
@ -747,6 +774,11 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
"cluster_ca_certificate": cluster.MasterAuth.ClusterCaCertificate, "cluster_ca_certificate": cluster.MasterAuth.ClusterCaCertificate,
}, },
} }
if len(cluster.MasterAuth.ClientCertificate) == 0 {
masterAuth[0]["client_certificate_config"] = []map[string]interface{}{
{"issue_client_certificate": false},
}
}
d.Set("master_auth", masterAuth) d.Set("master_auth", masterAuth)
if cluster.MasterAuthorizedNetworksConfig != nil { if cluster.MasterAuthorizedNetworksConfig != nil {
@ -1629,3 +1661,27 @@ func extractNodePoolInformationFromCluster(d *schema.ResourceData, config *Confi
cluster: d.Get("name").(string), cluster: d.Get("name").(string),
}, nil }, nil
} }
// We want to suppress diffs for empty or default client certificate configs, i.e:
// [{ "issue_client_certificate": true}] --> []
// [] -> [{ "issue_client_certificate": true}]
func masterAuthClientCertCfgSuppress(k, old, new string, r *schema.ResourceData) bool {
var clientConfig map[string]interface{}
if v, ok := r.GetOk("master_auth"); ok {
masterAuths := v.([]interface{})
masterAuth := masterAuths[0].(map[string]interface{})
cfgs := masterAuth["client_certificate_config"].([]interface{})
if len(cfgs) > 0 {
clientConfig = cfgs[0].(map[string]interface{})
}
}
if strings.HasSuffix(k, "client_certificate_config.#") && old == "0" && new == "1" {
// nil --> { "issue_client_certificate": true }
if issueCert, ok := clientConfig["issue_client_certificate"]; ok {
return issueCert.(bool)
}
}
return strings.HasSuffix(k, ".issue_client_certificate") && old == "" && new == "true"
}

View File

@ -104,7 +104,7 @@ func TestAccContainerCluster_withAddons(t *testing.T) {
}) })
} }
func TestAccContainerCluster_withMasterAuth(t *testing.T) { func TestAccContainerCluster_withMasterAuthConfig(t *testing.T) {
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
@ -115,7 +115,7 @@ func TestAccContainerCluster_withMasterAuth(t *testing.T) {
{ {
Config: testAccContainerCluster_withMasterAuth(), Config: testAccContainerCluster_withMasterAuth(),
}, },
resource.TestStep{ {
ResourceName: "google_container_cluster.with_master_auth", ResourceName: "google_container_cluster.with_master_auth",
ImportStateIdPrefix: "us-central1-a/", ImportStateIdPrefix: "us-central1-a/",
ImportState: true, ImportState: true,
@ -125,6 +125,30 @@ func TestAccContainerCluster_withMasterAuth(t *testing.T) {
}) })
} }
func TestAccContainerCluster_withMasterAuthConfig_NoCert(t *testing.T) {
t.Parallel()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withMasterAuthNoCert(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.with_master_auth_no_cert", "master_auth.0.client_certificate", ""),
),
},
{
ResourceName: "google_container_cluster.with_master_auth_no_cert",
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) {
t.Parallel() t.Parallel()
@ -1300,6 +1324,40 @@ resource "google_container_cluster" "with_master_auth" {
}`, acctest.RandString(10)) }`, acctest.RandString(10))
} }
func testAccContainerCluster_updateMasterAuthNoCert() string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_master_auth" {
name = "cluster-test-%s"
zone = "us-central1-a"
initial_node_count = 3
master_auth {
username = "mr.yoda"
password = "adoy.rm.123456789"
client_certificate_config {
issue_client_certificate = false
}
}
}`, acctest.RandString(10))
}
func testAccContainerCluster_withMasterAuthNoCert() string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_master_auth_no_cert" {
name = "cluster-test-%s"
zone = "us-central1-a"
initial_node_count = 3
master_auth {
username = "mr.yoda"
password = "adoy.rm.123456789"
client_certificate_config {
issue_client_certificate = false
}
}
}`, acctest.RandString(10))
}
func testAccContainerCluster_withNetworkPolicyEnabled(clusterName string) string { func testAccContainerCluster_withNetworkPolicyEnabled(clusterName string) string {
return fmt.Sprintf(` return fmt.Sprintf(`
resource "google_container_cluster" "with_network_policy_enabled" { resource "google_container_cluster" "with_network_policy_enabled" {

View File

@ -16,10 +16,6 @@ import (
"google.golang.org/api/googleapi" "google.golang.org/api/googleapi"
) )
const emptyTFDefinition = `
# empty def
`
func TestExtractInitTimeout(t *testing.T) { func TestExtractInitTimeout(t *testing.T) {
t.Parallel() t.Parallel()

View File

@ -169,6 +169,10 @@ func testAccCheckGoogleProjectOrganizationListPolicyAll(n, policyType string) re
return err return err
} }
if policy.ListPolicy == nil {
return nil
}
if len(policy.ListPolicy.AllowedValues) > 0 || len(policy.ListPolicy.DeniedValues) > 0 { if len(policy.ListPolicy.AllowedValues) > 0 || len(policy.ListPolicy.DeniedValues) > 0 {
return fmt.Errorf("The `values` field shouldn't be set") return fmt.Errorf("The `values` field shouldn't be set")
} }

View File

@ -0,0 +1,246 @@
package google
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccSpannerDatabaseIamBinding(t *testing.T) {
t.Parallel()
account := acctest.RandomWithPrefix("tf-test")
role := "roles/spanner.databaseAdmin"
project := getTestProjectFromEnv()
database := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
instance := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccSpannerDatabaseIamBinding_basic(account, instance, database, role),
},
resource.TestStep{
ResourceName: "google_spanner_database_iam_binding.foo",
ImportStateId: fmt.Sprintf("%s %s", spannerDatabaseId{
Project: project,
Instance: instance,
Database: database,
}.terraformId(), role),
ImportState: true,
ImportStateVerify: true,
},
{
// Test Iam Binding update
Config: testAccSpannerDatabaseIamBinding_update(account, instance, database, role),
},
resource.TestStep{
ResourceName: "google_spanner_database_iam_binding.foo",
ImportStateId: fmt.Sprintf("%s %s", spannerDatabaseId{
Project: project,
Instance: instance,
Database: database,
}.terraformId(), role),
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccSpannerDatabaseIamMember(t *testing.T) {
t.Parallel()
project := getTestProjectFromEnv()
account := acctest.RandomWithPrefix("tf-test")
role := "roles/spanner.databaseAdmin"
database := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
instance := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
// Test Iam Member creation (no update for member, no need to test)
Config: testAccSpannerDatabaseIamMember_basic(account, instance, database, role),
},
resource.TestStep{
ResourceName: "google_spanner_database_iam_member.foo",
ImportStateId: fmt.Sprintf("%s %s serviceAccount:%s@%s.iam.gserviceaccount.com", spannerDatabaseId{
Instance: instance,
Database: database,
Project: project,
}.terraformId(), role, account, project),
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccSpannerDatabaseIamPolicy(t *testing.T) {
t.Parallel()
project := getTestProjectFromEnv()
account := acctest.RandomWithPrefix("tf-test")
role := "roles/spanner.databaseAdmin"
database := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
instance := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccSpannerDatabaseIamPolicy_basic(account, instance, database, role),
},
// Test a few import formats
resource.TestStep{
ResourceName: "google_spanner_database_iam_policy.foo",
ImportStateId: fmt.Sprintf("%s", spannerDatabaseId{
Instance: instance,
Database: database,
Project: project,
}.terraformId()),
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccSpannerDatabaseIamBinding_basic(account, instance, database, roleId string) string {
return fmt.Sprintf(`
resource "google_service_account" "test_account" {
account_id = "%s"
display_name = "Spanner Iam Testing Account"
}
resource "google_spanner_instance" "instance" {
name = "%s"
config = "regional-us-central1"
display_name = "%s"
num_nodes = 1
}
resource "google_spanner_database" "database" {
instance = "${google_spanner_instance.instance.name}"
name = "%s"
}
resource "google_spanner_database_iam_binding" "foo" {
project = "${google_spanner_database.database.project}"
database = "${google_spanner_database.database.name}"
instance = "${google_spanner_database.database.instance}"
role = "%s"
members = ["serviceAccount:${google_service_account.test_account.email}"]
}
`, account, instance, instance, database, roleId)
}
func testAccSpannerDatabaseIamBinding_update(account, instance, database, roleId string) string {
return fmt.Sprintf(`
resource "google_service_account" "test_account" {
account_id = "%s"
display_name = "Spanner Iam Testing Account"
}
resource "google_service_account" "test_account_2" {
account_id = "%s-2"
display_name = "Spanner Iam Testing Account"
}
resource "google_spanner_instance" "instance" {
name = "%s"
config = "regional-us-central1"
display_name = "%s"
num_nodes = 1
}
resource "google_spanner_database" "database" {
instance = "${google_spanner_instance.instance.name}"
name = "%s"
}
resource "google_spanner_database_iam_binding" "foo" {
project = "${google_spanner_database.database.project}"
database = "${google_spanner_database.database.name}"
instance = "${google_spanner_database.database.instance}"
role = "%s"
members = [
"serviceAccount:${google_service_account.test_account.email}",
"serviceAccount:${google_service_account.test_account_2.email}"
]
}
`, account, account, instance, instance, database, roleId)
}
func testAccSpannerDatabaseIamMember_basic(account, instance, database, roleId string) string {
return fmt.Sprintf(`
resource "google_service_account" "test_account" {
account_id = "%s"
display_name = "Spanner Iam Testing Account"
}
resource "google_spanner_instance" "instance" {
name = "%s"
config = "regional-us-central1"
display_name = "%s"
num_nodes = 1
}
resource "google_spanner_database" "database" {
instance = "${google_spanner_instance.instance.name}"
name = "%s"
}
resource "google_spanner_database_iam_member" "foo" {
project = "${google_spanner_database.database.project}"
database = "${google_spanner_database.database.name}"
instance = "${google_spanner_database.database.instance}"
role = "%s"
member = "serviceAccount:${google_service_account.test_account.email}"
}
`, account, instance, instance, database, roleId)
}
func testAccSpannerDatabaseIamPolicy_basic(account, instance, database, roleId string) string {
return fmt.Sprintf(`
resource "google_service_account" "test_account" {
account_id = "%s"
display_name = "Spanner Iam Testing Account"
}
resource "google_spanner_instance" "instance" {
name = "%s"
config = "regional-us-central1"
display_name = "%s"
num_nodes = 1
}
resource "google_spanner_database" "database" {
instance = "${google_spanner_instance.instance.name}"
name = "%s"
}
data "google_iam_policy" "foo" {
binding {
role = "%s"
members = ["serviceAccount:${google_service_account.test_account.email}"]
}
}
resource "google_spanner_database_iam_policy" "foo" {
project = "${google_spanner_database.database.project}"
database = "${google_spanner_database.database.name}"
instance = "${google_spanner_database.database.instance}"
policy_data = "${data.google_iam_policy.foo.policy_data}"
}
`, account, instance, instance, database, roleId)
}

View File

@ -695,7 +695,7 @@ func resourceSqlDatabaseInstanceCreate(d *schema.ResourceData, meta interface{})
err = retryTime(func() error { err = retryTime(func() error {
users, err = config.clientSqlAdmin.Users.List(project, instance.Name).Do() users, err = config.clientSqlAdmin.Users.List(project, instance.Name).Do()
return err return err
}, 3) }, 5)
if err != nil { if err != nil {
return fmt.Errorf("Error, attempting to list users associated with instance %s: %s", instance.Name, err) return fmt.Errorf("Error, attempting to list users associated with instance %s: %s", instance.Name, err)
} }

View File

@ -115,10 +115,10 @@ func resourceSqlUserRead(d *schema.ResourceData, meta interface{}) error {
var users *sqladmin.UsersListResponse var users *sqladmin.UsersListResponse
err = nil err = nil
err = retry(func() error { err = retryTime(func() error {
users, err = config.clientSqlAdmin.Users.List(project, instance).Do() users, err = config.clientSqlAdmin.Users.List(project, instance).Do()
return err return err
}) }, 5)
if err != nil { if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("SQL User %q in instance %q", name, instance)) return handleNotFoundError(err, d, fmt.Sprintf("SQL User %q in instance %q", name, instance))
} }

View File

@ -91,6 +91,10 @@ func testAccCheckGoogleSqlUserExists(n string) resource.TestCheckFunc {
users, err := config.clientSqlAdmin.Users.List(config.Project, users, err := config.clientSqlAdmin.Users.List(config.Project,
instance).Do() instance).Do()
if err != nil {
return err
}
for _, user := range users.Items { for _, user := range users.Items {
if user.Name == name && user.Host == host { if user.Name == name && user.Host == host {
return nil return nil

View File

@ -70,6 +70,10 @@ func GetResourceNameFromSelfLink(link string) string {
return parts[len(parts)-1] return parts[len(parts)-1]
} }
func NameFromSelfLinkStateFunc(v interface{}) string {
return GetResourceNameFromSelfLink(v.(string))
}
func StoreResourceName(resourceLink interface{}) string { func StoreResourceName(resourceLink interface{}) string {
return GetResourceNameFromSelfLink(resourceLink.(string)) return GetResourceNameFromSelfLink(resourceLink.(string))
} }

View File

@ -55,6 +55,15 @@ func TestReplaceVars(t *testing.T) {
}, },
Expected: "projects/project1/regions/region1/subnetworks/subnetwork1", Expected: "projects/project1/regions/region1/subnetworks/subnetwork1",
}, },
"regional schema self-link region": {
Template: "projects/{{project}}/regions/{{region}}/subnetworks/{{name}}",
SchemaValues: map[string]interface{}{
"project": "project1",
"region": "https://www.googleapis.com/compute/v1/projects/project1/regions/region1",
"name": "subnetwork1",
},
Expected: "projects/project1/regions/region1/subnetworks/subnetwork1",
},
"zonal schema values": { "zonal schema values": {
Template: "projects/{{project}}/zones/{{zone}}/instances/{{name}}", Template: "projects/{{project}}/zones/{{zone}}/instances/{{name}}",
SchemaValues: map[string]interface{}{ SchemaValues: map[string]interface{}{
@ -64,6 +73,15 @@ func TestReplaceVars(t *testing.T) {
}, },
Expected: "projects/project1/zones/zone1/instances/instance1", Expected: "projects/project1/zones/zone1/instances/instance1",
}, },
"zonal schema self-link zone": {
Template: "projects/{{project}}/zones/{{zone}}/instances/{{name}}",
SchemaValues: map[string]interface{}{
"project": "project1",
"zone": "https://www.googleapis.com/compute/v1/projects/project1/zones/zone1",
"name": "instance1",
},
Expected: "projects/project1/zones/zone1/instances/instance1",
},
} }
for tn, tc := range cases { for tn, tc := range cases {

View File

@ -118,18 +118,6 @@ func getZonalBetaResourceFromRegion(getResource func(string) (interface{}, error
return nil, nil return nil, nil
} }
func getNetworkNameFromSelfLink(network string) (string, error) {
if !strings.HasPrefix(network, "https://www.googleapis.com/compute/") {
return network, nil
}
// extract the network name from SelfLink URL
networkName := network[strings.LastIndex(network, "/")+1:]
if networkName == "" {
return "", fmt.Errorf("network url not valid")
}
return networkName, nil
}
func getRouterLockName(region string, router string) string { func getRouterLockName(region string, router string) string {
return fmt.Sprintf("router/%s/%s", region, router) return fmt.Sprintf("router/%s/%s", region, router)
} }
@ -298,6 +286,20 @@ func mergeSchemas(a, b map[string]*schema.Schema) map[string]*schema.Schema {
return merged return merged
} }
func mergeResourceMaps(a, b map[string]*schema.Resource) map[string]*schema.Resource {
merged := make(map[string]*schema.Resource)
for k, v := range a {
merged[k] = v
}
for k, v := range b {
merged[k] = v
}
return merged
}
func retry(retryFunc func() error) error { func retry(retryFunc func() error) error {
return retryTime(retryFunc, 1) return retryTime(retryFunc, 1)
} }

View File

@ -20,6 +20,10 @@ const (
RFC1035NameTemplate = "[a-z](?:[-a-z0-9]{%d,%d}[a-z0-9])" RFC1035NameTemplate = "[a-z](?:[-a-z0-9]{%d,%d}[a-z0-9])"
CloudIoTIdRegex = "^[a-zA-Z][-a-zA-Z0-9._+~%]{2,254}$" CloudIoTIdRegex = "^[a-zA-Z][-a-zA-Z0-9._+~%]{2,254}$"
// Format of default Compute service accounts created by Google
// ${PROJECT_ID}-compute@developer.gserviceaccount.com where PROJECT_ID is an int64 (max 20 digits)
ComputeServiceAccountNameRegex = "[0-9]{1,20}-compute@developer.gserviceaccount.com"
) )
var ( var (
@ -29,8 +33,20 @@ var (
// 4 and 28 since the first and last character are excluded. // 4 and 28 since the first and last character are excluded.
ServiceAccountNameRegex = fmt.Sprintf(RFC1035NameTemplate, 4, 28) ServiceAccountNameRegex = fmt.Sprintf(RFC1035NameTemplate, 4, 28)
ProjectNameInDNSFormRegex = "[-a-z0-9\\.]{1,63}" ServiceAccountLinkRegexPrefix = "projects/" + ProjectRegex + "/serviceAccounts/"
ServiceAccountLinkRegex = "projects/" + ProjectRegex + "/serviceAccounts/" + ServiceAccountNameRegex + "@" + ProjectNameInDNSFormRegex + "\\.iam\\.gserviceaccount\\.com$" PossibleServiceAccountNames = []string{
AppEngineServiceAccountNameRegex,
ComputeServiceAccountNameRegex,
CreatedServiceAccountNameRegex,
}
ServiceAccountLinkRegex = ServiceAccountLinkRegexPrefix + "(" + strings.Join(PossibleServiceAccountNames, "|") + ")"
// Format of service accounts created through the API
CreatedServiceAccountNameRegex = fmt.Sprintf(RFC1035NameTemplate, 4, 28) + "@" + ProjectNameInDNSFormRegex + "\\.iam\\.gserviceaccount\\.com$"
ProjectNameInDNSFormRegex = "[-a-z0-9\\.]{1,63}"
// Format of default App Engine service accounts created by Google
AppEngineServiceAccountNameRegex = ProjectRegex + "@appspot.gserviceaccount.com"
) )
var rfc1918Networks = []string{ var rfc1918Networks = []string{

View File

@ -117,6 +117,8 @@ func TestValidateServiceAccountLink(t *testing.T) {
{TestName: "valid with dash", Value: "projects/my-project/serviceAccounts/svcacct@my-project.iam.gserviceaccount.com"}, {TestName: "valid with dash", Value: "projects/my-project/serviceAccounts/svcacct@my-project.iam.gserviceaccount.com"},
{TestName: "valid with colon", Value: "projects/my:project/serviceAccounts/svcacct@project.my.iam.gserviceaccount.com"}, {TestName: "valid with colon", Value: "projects/my:project/serviceAccounts/svcacct@project.my.iam.gserviceaccount.com"},
{TestName: "valid with dot and colon", Value: "projects/my.thing:project/serviceAccounts/svcacct@project.my.thing.iam.gserviceaccount.com"}, {TestName: "valid with dot and colon", Value: "projects/my.thing:project/serviceAccounts/svcacct@project.my.thing.iam.gserviceaccount.com"},
{TestName: "valid with compute default service account", Value: "projects/my-project/serviceAccounts/123456-compute@developer.gserviceaccount.com"},
{TestName: "valid with app engine default service account", Value: "projects/my-project/serviceAccounts/my-project@appspot.gserviceaccount.com"},
// Errors // Errors
{TestName: "multiple colons", Value: "projects/my:project:thing/serviceAccounts/svcacct@thing.project.my.iam.gserviceaccount.com", ExpectError: true}, {TestName: "multiple colons", Value: "projects/my:project:thing/serviceAccounts/svcacct@thing.project.my.iam.gserviceaccount.com", ExpectError: true},

View File

@ -1,26 +1,23 @@
<!--
----------------------------------------------------------------------------
*** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
----------------------------------------------------------------------------
This file is automatically generated by Magic Modules and manual
changes will be clobbered when the file is regenerated.
Please read more about how to change this file in
.github/CONTRIBUTING.md.
----------------------------------------------------------------------------
-->
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_backend_bucket" page_title: "Google: google_compute_backend_bucket"
sidebar_current: "docs-google-compute-backend-bucket" sidebar_current: "docs-google-compute-backend-bucket"
description: |- description: |-
Backend buckets allow you to use Google Cloud Storage buckets with HTTP(S) Backend buckets allow you to use Google Cloud Storage buckets with HTTP(S)
load balancing. load balancing.
--- ---
# google\_compute\_backend\_bucket # google\_compute\_backend\_bucket
@ -28,7 +25,7 @@ load balancing.
Backend buckets allow you to use Google Cloud Storage buckets with HTTP(S) Backend buckets allow you to use Google Cloud Storage buckets with HTTP(S)
load balancing. load balancing.
An HTTP(S) load balancing can direct traffic to specified URLs to a An HTTP(S) load balancer can direct traffic to specified URLs to a
backend bucket rather than a backend service. It can send requests for backend bucket rather than a backend service. It can send requests for
static content to a Cloud Storage bucket and requests for dynamic content static content to a Cloud Storage bucket and requests for dynamic content
a virtual machine instance. a virtual machine instance.

View File

@ -1,17 +1,34 @@
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_global_address" page_title: "Google: google_compute_global_address"
sidebar_current: "docs-google-compute-global-address" sidebar_current: "docs-google-compute-global-address"
description: |- description: |-
Creates a static global IP address resource for a Google Compute Engine project. Represents a Global Address resource.
--- ---
# google\_compute\_global\_address # google\_compute\_global\_address
Creates a static IP address resource global to a Google Compute Engine project. For more information see Represents a Global Address resource. Global addresses are used for
[the official documentation](https://cloud.google.com/compute/docs/instances-and-network) and HTTP(S) load balancing.
[API](https://cloud.google.com/compute/docs/reference/latest/globalAddresses).
To get more information about GlobalAddress, see:
* [API documentation](https://cloud.google.com/compute/docs/reference/latest/globalAddresses)
* How-to Guides
* [Reserving a Static External IP Address](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address)
## Example Usage ## Example Usage
@ -25,29 +42,56 @@ resource "google_compute_global_address" "default" {
The following arguments are supported: The following arguments are supported:
* `name` - (Required) A unique name for the resource, required by GCE. * `name` -
Changing this forces a new resource to be created. (Required)
Name of the resource. Provided by the client when the resource is
created. The name must be 1-63 characters long, and comply with
RFC1035. Specifically, the name must be 1-63 characters long and
match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means
the first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.
- - - - - -
* `project` - (Optional) The ID of the project in which the resource belongs. If it * `description` -
is not provided, the provider project is used. (Optional)
An optional description of this resource.
Provide this property when you create the resource.
* `ip_version` -
(Optional)
The IP Version that will be used by this address. Valid options are
IPV4 or IPV6. The default value is IPV4.
* `project` (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.
* `ip_version` - (Optional) The IP Version that will be used by this address. One of `"IPV4"` or `"IPV6"`.
## Attributes Reference ## Attributes Reference
In addition to the arguments listed above, the following computed attributes are In addition to the arguments listed above, the following computed attributes are exported:
exported:
* `address` - The assigned address.
* `address` -
The static external IP address represented by this resource.
* `creation_timestamp` -
Creation timestamp in RFC3339 text format.
* `self_link` - The URI of the created resource. * `self_link` - The URI of the created resource.
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import ## Import
Global addresses can be imported using the `name`, e.g. GlobalAddress can be imported using any of these accepted formats:
``` ```
$ terraform import google_compute_global_address.default global-appserver-ip $ terraform import google_compute_global_address.default projects/{{project}}/global/addresses/{{name}}
$ terraform import google_compute_global_address.default {{project}}/{{name}}
$ terraform import google_compute_global_address.default {{name}}
``` ```

View File

@ -1,20 +1,17 @@
<!--
----------------------------------------------------------------------------
*** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
----------------------------------------------------------------------------
This file is automatically generated by Magic Modules and manual
changes will be clobbered when the file is regenerated.
Please read more about how to change this file in
.github/CONTRIBUTING.md.
----------------------------------------------------------------------------
-->
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_http_health_check" page_title: "Google: google_compute_http_health_check"
sidebar_current: "docs-google-compute-http-health-check" sidebar_current: "docs-google-compute-http-health-check"

View File

@ -1,20 +1,17 @@
<!--
----------------------------------------------------------------------------
*** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
----------------------------------------------------------------------------
This file is automatically generated by Magic Modules and manual
changes will be clobbered when the file is regenerated.
Please read more about how to change this file in
.github/CONTRIBUTING.md.
----------------------------------------------------------------------------
-->
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_https_health_check" page_title: "Google: google_compute_https_health_check"
sidebar_current: "docs-google-compute-https-health-check" sidebar_current: "docs-google-compute-https-health-check"

View File

@ -1,18 +1,35 @@
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_target_http_proxy" page_title: "Google: google_compute_target_http_proxy"
sidebar_current: "docs-google-compute-target-http-proxy" sidebar_current: "docs-google-compute-target-http-proxy"
description: |- description: |-
Creates a Target HTTP Proxy resource in GCE. Represents a TargetHttpProxy resource, which is used by one or more global
forwarding rule to route incoming HTTP requests to a URL map.
--- ---
# google\_compute\_target\_http\_proxy # google\_compute\_target\_http\_proxy
Creates a target HTTP proxy resource in GCE. For more information see Represents a TargetHttpProxy resource, which is used by one or more global
[the official forwarding rule to route incoming HTTP requests to a URL map.
documentation](https://cloud.google.com/compute/docs/load-balancing/http/target-proxies) and
[API](https://cloud.google.com/compute/docs/reference/latest/targetHttpProxies).
To get more information about TargetHttpProxy, see:
* [API documentation](https://cloud.google.com/compute/docs/reference/latest/targetHttpProxies)
* How-to Guides
* [Official Documentation](https://cloud.google.com/compute/docs/load-balancing/http/target-proxies)
## Example Usage ## Example Usage
@ -66,34 +83,55 @@ resource "google_compute_http_health_check" "default" {
The following arguments are supported: The following arguments are supported:
* `name` - (Required) A unique name for the resource, required by GCE. Changing * `name` -
this forces a new resource to be created. (Required)
Name of the resource. Provided by the client when the resource is
created. The name must be 1-63 characters long, and comply with
RFC1035. Specifically, the name must be 1-63 characters long and match
the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the
first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.
* `url_map` -
(Required)
A reference to UrlMap resource
* `url_map` - (Required) The URL of a URL Map resource that defines the mapping
from the URL to the BackendService.
* `project` - (Optional) The ID of the project in which the resource belongs. If it
is not provided, the provider project is used.
- - - - - -
* `description` - (Optional) A description of this resource. Changing this * `description` -
forces a new resource to be created. (Optional)
An optional description of this 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 ## Attributes Reference
In addition to the arguments listed above, the following computed attributes are In addition to the arguments listed above, the following computed attributes are exported:
exported:
* `proxy_id` - A unique ID assigned by GCE.
* `creation_timestamp` -
Creation timestamp in RFC3339 text format.
* `proxy_id` -
The unique identifier for the resource.
* `self_link` - The URI of the created resource. * `self_link` - The URI of the created resource.
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `update` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import ## Import
Target HTTP Proxy can be imported using the `name`, e.g. TargetHttpProxy can be imported using any of these accepted formats:
``` ```
$ terraform import compute_target_http_proxy.foobar foobar $ terraform import google_compute_target_http_proxy.default projects/{{project}}/global/targetHttpProxies/{{name}}
$ terraform import google_compute_target_http_proxy.default {{project}}/{{name}}
$ terraform import google_compute_target_http_proxy.default {{name}}
``` ```

View File

@ -1,18 +1,35 @@
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_target_https_proxy" page_title: "Google: google_compute_target_https_proxy"
sidebar_current: "docs-google-compute-target-https-proxy" sidebar_current: "docs-google-compute-target-https-proxy"
description: |- description: |-
Creates a Target HTTPS Proxy resource in GCE. Represents a TargetHttpsProxy resource, which is used by one or more
global forwarding rule to route incoming HTTPS requests to a URL map.
--- ---
# google\_compute\_target\_https\_proxy # google\_compute\_target\_https\_proxy
Creates a target HTTPS proxy resource in GCE. For more information see Represents a TargetHttpsProxy resource, which is used by one or more
[the official global forwarding rule to route incoming HTTPS requests to a URL map.
documentation](https://cloud.google.com/compute/docs/load-balancing/http/target-proxies) and
[API](https://cloud.google.com/compute/docs/reference/latest/targetHttpsProxies).
To get more information about TargetHttpsProxy, see:
* [API documentation](https://cloud.google.com/compute/docs/reference/latest/targetHttpsProxies)
* How-to Guides
* [Official Documentation](https://cloud.google.com/compute/docs/load-balancing/http/target-proxies)
## Example Usage ## Example Usage
@ -74,36 +91,60 @@ resource "google_compute_http_health_check" "default" {
The following arguments are supported: The following arguments are supported:
* `name` - (Required) A unique name for the resource, required by GCE. Changing * `name` -
this forces a new resource to be created. (Required)
Name of the resource. Provided by the client when the resource is
created. The name must be 1-63 characters long, and comply with
RFC1035. Specifically, the name must be 1-63 characters long and match
the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the
first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.
* `ssl_certificates` -
(Required)
A list of SslCertificate resources that are used to authenticate
connections between users and the load balancer. Currently, exactly
one SSL certificate must be specified.
* `url_map` -
(Required)
A reference to UrlMap resource
* `ssl_certificates` - (Required) The URLs or names of the SSL Certificate resources
that authenticate connections between users and load balancing.
* `url_map` - (Required) The URL of a URL Map resource that defines the mapping
from the URL to the BackendService.
- - - - - -
* `description` - (Optional) A description of this resource. Changing this * `description` -
forces a new resource to be created. (Optional)
An optional description of this resource.
* `project` (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.
* `project` - (Optional) The ID of the project in which the resource belongs. If it
is not provided, the provider project is used.
## Attributes Reference ## Attributes Reference
In addition to the arguments listed above, the following computed attributes are In addition to the arguments listed above, the following computed attributes are exported:
exported:
* `proxy_id` - A unique ID assigned by GCE.
* `creation_timestamp` -
Creation timestamp in RFC3339 text format.
* `proxy_id` -
The unique identifier for the resource.
* `self_link` - The URI of the created resource. * `self_link` - The URI of the created resource.
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `update` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import ## Import
Target HTTPS Proxy can be imported using the `name`, e.g. TargetHttpsProxy can be imported using any of these accepted formats:
``` ```
$ terraform import compute_target_https_proxy.foobar foobar $ terraform import google_compute_target_https_proxy.default projects/{{project}}/global/targetHttpsProxies/{{name}}
$ terraform import google_compute_target_https_proxy.default {{project}}/{{name}}
$ terraform import google_compute_target_https_proxy.default {{name}}
``` ```

View File

@ -1,27 +1,24 @@
<!--
----------------------------------------------------------------------------
*** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
----------------------------------------------------------------------------
This file is automatically generated by Magic Modules and manual
changes will be clobbered when the file is regenerated.
Please read more about how to change this file in
.github/CONTRIBUTING.md.
----------------------------------------------------------------------------
-->
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_target_ssl_proxy" page_title: "Google: google_compute_target_ssl_proxy"
sidebar_current: "docs-google-compute-target-ssl-proxy" sidebar_current: "docs-google-compute-target-ssl-proxy"
description: |- description: |-
Represents a TargetSslProxy resource, which is used by one or more Represents a TargetSslProxy resource, which is used by one or more
global forwarding rule to route incoming SSL requests to a backend global forwarding rule to route incoming SSL requests to a backend
service. service.
--- ---
# google\_compute\_target\_ssl\_proxy # google\_compute\_target\_ssl\_proxy

View File

@ -1,18 +1,37 @@
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_target_tcp_proxy" page_title: "Google: google_compute_target_tcp_proxy"
sidebar_current: "docs-google-compute-target-tcp-proxy" sidebar_current: "docs-google-compute-target-tcp-proxy"
description: |- description: |-
Creates a Target TCP Proxy resource in GCE. Represents a TargetTcpProxy resource, which is used by one or more
global forwarding rule to route incoming TCP requests to a Backend
service.
--- ---
# google\_compute\_target\_tcp\_proxy # google\_compute\_target\_tcp\_proxy
Creates a target TCP proxy resource in GCE. For more information see Represents a TargetTcpProxy resource, which is used by one or more
[the official global forwarding rule to route incoming TCP requests to a Backend
documentation](https://cloud.google.com/compute/docs/load-balancing/tcp-ssl/tcp-proxy) and service.
[API](https://cloud.google.com/compute/docs/reference/latest/targetTcpProxies).
To get more information about TargetTcpProxy, see:
* [API documentation](https://cloud.google.com/compute/docs/reference/latest/targetTcpProxies)
* How-to Guides
* [Setting Up TCP proxy for Google Cloud Load Balancing](https://cloud.google.com/compute/docs/load-balancing/tcp-ssl/tcp-proxy)
## Example Usage ## Example Usage
@ -46,35 +65,59 @@ resource "google_compute_health_check" "default" {
The following arguments are supported: The following arguments are supported:
* `name` - (Required) A unique name for the resource, required by GCE. Changing * `name` -
this forces a new resource to be created. (Required)
Name of the resource. Provided by the client when the resource is
created. The name must be 1-63 characters long, and comply with
RFC1035. Specifically, the name must be 1-63 characters long and match
the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the
first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.
* `backend_service` -
(Required)
A reference to BackendService resource
* `backend_service` - (Required) The URL of a Backend Service resource to receive the matched traffic.
- - - - - -
* `proxy_header` - (Optional) Type of proxy header to append before sending * `description` -
data to the backend, either NONE or PROXY_V1 (default NONE). (Optional)
An optional description of this resource.
* `proxy_header` -
(Optional)
Specifies the type of proxy header to append before sending data to
the backend, either NONE or PROXY_V1. The default is NONE.
* `project` (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.
* `description` - (Optional) A description of this resource. Changing this
forces a new resource to be created.
* `project` - (Optional) The ID of the project in which the resource belongs. If it
is not provided, the provider project is used.
## Attributes Reference ## Attributes Reference
In addition to the arguments listed above, the following computed attributes are In addition to the arguments listed above, the following computed attributes are exported:
exported:
* `proxy_id` - A unique ID assigned by GCE.
* `creation_timestamp` -
Creation timestamp in RFC3339 text format.
* `proxy_id` -
The unique identifier for the resource.
* `self_link` - The URI of the created resource. * `self_link` - The URI of the created resource.
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `update` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import ## Import
TCP proxy can be imported using the `name`, e.g. TargetTcpProxy can be imported using any of these accepted formats:
``` ```
$ terraform import google_compute_target_tcp_proxy.default test $ terraform import google_compute_target_tcp_proxy.default projects/{{project}}/global/targetTcpProxies/{{name}}
$ terraform import google_compute_target_tcp_proxy.default {{project}}/{{name}}
$ terraform import google_compute_target_tcp_proxy.default {{name}}
``` ```

View File

@ -1,16 +1,32 @@
--- ---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google" layout: "google"
page_title: "Google: google_compute_vpn_gateway" page_title: "Google: google_compute_vpn_gateway"
sidebar_current: "docs-google-compute-vpn-gateway" sidebar_current: "docs-google-compute-vpn-gateway"
description: |- description: |-
Manages a VPN Gateway in the GCE network Represents a VPN gateway running in GCP.
--- ---
# google\_compute\_vpn\_gateway # google\_compute\_vpn\_gateway
Manages a VPN Gateway in the GCE network. For more info, read the Represents a VPN gateway running in GCP. This virtual device is managed
[documentation](https://cloud.google.com/compute/docs/vpn). by Google, but used only by you.
To get more information about VpnGateway, see:
* [API documentation](https://cloud.google.com/compute/docs/reference/rest/v1/targetVpnGateways)
## Example Usage ## Example Usage
@ -86,27 +102,55 @@ resource "google_compute_route" "route1" {
The following arguments are supported: The following arguments are supported:
* `name` - (Required) A unique name for the resource, required by GCE. Changing * `name` -
this forces a new resource to be created. (Required)
Name of the resource. Provided by the client when the resource is
created. The name must be 1-63 characters long, and comply with
RFC1035. Specifically, the name must be 1-63 characters long and
match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means
the first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.
* `network` -
(Required)
A reference to Network resource
* `network` - (Required) The name or resource link to the network this VPN gateway
is accepting traffic for. Changing this forces a new resource to be created.
- - - - - -
* `description` - (Optional) A description of the resource. * `description` -
Changing this forces a new resource to be created. (Optional)
An optional description of this resource.
* `region` -
(Optional)
A reference to Region resource
* `project` (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.
* `project` - (Optional) The ID of the project in which the resource belongs. If it
is not provided, the provider project is used.
* `region` - (Optional) The region this gateway should sit in. If not specified,
the project region will be used. Changing this forces a new resource to be
created.
## Attributes Reference ## Attributes Reference
In addition to the arguments listed above, the following computed attributes are In addition to the arguments listed above, the following computed attributes are exported:
exported:
* `creation_timestamp` -
Creation timestamp in RFC3339 text format.
* `self_link` - The URI of the created resource. * `self_link` - The URI of the created resource.
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import
VpnGateway can be imported using any of these accepted formats:
```
$ terraform import google_compute_vpn_gateway.default projects/{{project}}/regions/{{region}}/targetVpnGateways/{{name}}
$ terraform import google_compute_vpn_gateway.default {{project}}/{{region}}/{{name}}
$ terraform import google_compute_vpn_gateway.default {{name}}
```

View File

@ -99,7 +99,7 @@ resource "google_dns_managed_zone" "prod" {
### Adding an SPF record ### Adding an SPF record
`\"` must be added around your `rrdatas` for a SPF record. Otherwise `rrdatas` string gets split on spaces. Quotes (`""`) must be added around your `rrdatas` for a SPF record. Otherwise `rrdatas` string gets split on spaces.
```hcl ```hcl
resource "google_dns_record_set" "spf" { resource "google_dns_record_set" "spf" {

View File

@ -0,0 +1,126 @@
---
layout: "google"
page_title: "Google: google_spanner_database_iam"
sidebar_current: "docs-google-spanner-database-iam"
description: |-
Collection of resources to manage IAM policy for a Spanner database.
---
# IAM policy for Spanner databases
Three different resources help you manage your IAM policy for a Spanner database. Each of these resources serves a different use case:
* `google_spanner_database_iam_policy`: Authoritative. Sets the IAM policy for the database and replaces any existing policy already attached.
~> **Warning:** It's entirely possibly to lock yourself out of your database using `google_spanner_database_iam_policy`. Any permissions granted by default will be removed unless you include them in your config.
* `google_spanner_database_iam_binding`: Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the database are preserved.
* `google_spanner_database_iam_member`: Non-authoritative. Updates the IAM policy to grant a role to a new member. Other members for the role for the database are preserved.
~> **Note:** `google_spanner_database_iam_policy` **cannot** be used in conjunction with `google_spanner_database_iam_binding` and `google_spanner_database_iam_member` or they will fight over what your policy should be.
~> **Note:** `google_spanner_database_iam_binding` resources **can be** used in conjunction with `google_spanner_database_iam_member` resources **only if** they do not grant privilege to the same role.
## google\_spanner\_database\_iam\_policy
```hcl
data "google_iam_policy" "admin" {
binding {
role = "roles/editor"
members = [
"user:jane@example.com",
]
}
}
resource "google_spanner_database_iam_policy" "database" {
instance = "your-instance-name"
database = "your-database-name"
policy_data = "${data.google_iam_policy.admin.policy_data}"
}
```
## google\_spanner\_database\_iam\_binding
```hcl
resource "google_spanner_database_iam_binding" "database" {
instance = "your-instance-name"
database = "your-database-name"
role = "roles/compute.networkUser"
members = [
"user:jane@example.com",
]
}
```
## google\_spanner\_database\_iam\_member
```hcl
resource "google_spanner_database_iam_member" "database" {
instance = "your-instance-name"
database = "your-database-name"
role = "roles/compute.networkUser"
member = "user:jane@example.com"
}
```
## Argument Reference
The following arguments are supported:
* `database` - (Required) The name of the Spanner database.
* `instance` - (Required) The name of the Spanner instance the database belongs to.
* `member/members` - (Required) Identities that will be granted the privilege in `role`.
Each entry can have one of the following values:
* **allUsers**: A special identifier that represents anyone who is on the internet; with or without a Google account.
* **allAuthenticatedUsers**: A special identifier that represents anyone who is authenticated with a Google account or a service account.
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com.
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
* **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com.
* **domain:{domain}**: A Google Apps domain name that represents all the users of that domain. For example, google.com or example.com.
* `role` - (Required) The role that should be applied. Only one
`google_spanner_database_iam_binding` can be used per role. Note that custom roles must be of the format
`[projects|organizations]/{parent-name}/roles/{role-name}`.
* `policy_data` - (Required only by `google_spanner_database_iam_policy`) The policy data generated by
a `google_iam_policy` data source.
* `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:
* `etag` - (Computed) The etag of the database's IAM policy.
## Import
For all import syntaxes, the "resource in question" can take any of the following forms:
* {{project}}/{{instance}}/{{database}}
* {{instance}}/{{database}} (project is taken from provider project)
IAM member imports use space-delimited identifiers; the resource in question, the role, and the account, e.g.
```
$ terraform import google_spanner_database_iam_member.database "project-name/instance-name/database-name roles/viewer foo@example.com"
```
IAM binding imports use space-delimited identifiers; the resource in question and the role, e.g.
```
$ terraform import google_spanner_database_iam_binding.database "project-name/instance-name/database-name roles/viewer"
```
IAM policy imports use the identifier of the resource in question, e.g.
```
$ terraform import google_spanner_database_iam_policy.database project-name/instance-name/database-name
```

View File

@ -520,13 +520,22 @@
<li<%= sidebar_current("docs-google-spanner") %>> <li<%= sidebar_current("docs-google-spanner") %>>
<a href="#">Google Spanner Resources</a> <a href="#">Google Spanner Resources</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible">
<li<%= sidebar_current("docs-google-spanner-instance") %>>
<a href="/docs/providers/google/r/spanner_instance.html">google_spanner_instance</a>
</li>
<li<%= sidebar_current("docs-google-spanner-database") %>> <li<%= sidebar_current("docs-google-spanner-database") %>>
<a href="/docs/providers/google/r/spanner_database.html">google_spanner_database</a> <a href="/docs/providers/google/r/spanner_database.html">google_spanner_database</a>
</li> </li>
<li<%= sidebar_current("docs-google-spanner-database-iam") %>>
<a href="/docs/providers/google/r/spanner_database_iam.html">google_spanner_database_iam_binding</a>
</li>
<li<%= sidebar_current("docs-google-spanner-database-iam") %>>
<a href="/docs/providers/google/r/spanner_database_iam.html">google_spanner_database_iam_member</a>
</li>
<li<%= sidebar_current("docs-google-spanner-database-iam") %>>
<a href="/docs/providers/google/r/spanner_database_iam.html">google_spanner_database_iam_policy</a>
</li>
<li<%= sidebar_current("docs-google-spanner-instance") %>>
<a href="/docs/providers/google/r/spanner_instance.html">google_spanner_instance</a>
</li>
</ul> </ul>
</li> </li>