From 0d32bc13bbdbf3630b47fe18a6f660a695de46dd Mon Sep 17 00:00:00 2001 From: Heng Lu Date: Thu, 26 May 2022 13:32:10 +0800 Subject: [PATCH 1/2] new resource `azurerm_spring_cloud_api_portal_custom_domain` --- .../services/springcloud/client/client.go | 73 +++++---- .../spring_cloud_api_portal_custom_domain.go | 81 ++++++++++ ...ing_cloud_api_portal_custom_domain_test.go | 144 +++++++++++++++++ internal/services/springcloud/registration.go | 1 + internal/services/springcloud/resourceids.go | 1 + ...cloud_api_portal_custom_domain_resource.go | 146 ++++++++++++++++++ ..._api_portal_custom_domain_resource_test.go | 109 +++++++++++++ ...pring_cloud_api_portal_custom_domain_id.go | 23 +++ ..._cloud_api_portal_custom_domain_id_test.go | 100 ++++++++++++ ...oud_api_portal_custom_domain.html.markdown | 82 ++++++++++ 10 files changed, 726 insertions(+), 34 deletions(-) create mode 100644 internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go create mode 100644 internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain_test.go create mode 100644 internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource.go create mode 100644 internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource_test.go create mode 100644 internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id.go create mode 100644 internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id_test.go create mode 100644 website/docs/r/spring_cloud_api_portal_custom_domain.html.markdown diff --git a/internal/services/springcloud/client/client.go b/internal/services/springcloud/client/client.go index 205cf812d0cb..0b427c995384 100644 --- a/internal/services/springcloud/client/client.go +++ b/internal/services/springcloud/client/client.go @@ -6,29 +6,33 @@ import ( ) type Client struct { - APIPortalClient *appplatform.APIPortalsClient - AppsClient *appplatform.AppsClient - BindingsClient *appplatform.BindingsClient - BuildPackBindingClient *appplatform.BuildpackBindingClient - BuildServiceBuilderClient *appplatform.BuildServiceBuilderClient - CertificatesClient *appplatform.CertificatesClient - ConfigServersClient *appplatform.ConfigServersClient - ConfigurationServiceClient *appplatform.ConfigurationServicesClient - CustomDomainsClient *appplatform.CustomDomainsClient - GatewayClient *appplatform.GatewaysClient - GatewayCustomDomainClient *appplatform.GatewayCustomDomainsClient - GatewayRouteConfigClient *appplatform.GatewayRouteConfigsClient - MonitoringSettingsClient *appplatform.MonitoringSettingsClient - DeploymentsClient *appplatform.DeploymentsClient - ServicesClient *appplatform.ServicesClient - ServiceRegistryClient *appplatform.ServiceRegistriesClient - StoragesClient *appplatform.StoragesClient + APIPortalClient *appplatform.APIPortalsClient + APIPortalCustomDomainClient *appplatform.APIPortalCustomDomainsClient + AppsClient *appplatform.AppsClient + BindingsClient *appplatform.BindingsClient + BuildPackBindingClient *appplatform.BuildpackBindingClient + BuildServiceBuilderClient *appplatform.BuildServiceBuilderClient + CertificatesClient *appplatform.CertificatesClient + ConfigServersClient *appplatform.ConfigServersClient + ConfigurationServiceClient *appplatform.ConfigurationServicesClient + CustomDomainsClient *appplatform.CustomDomainsClient + GatewayClient *appplatform.GatewaysClient + GatewayCustomDomainClient *appplatform.GatewayCustomDomainsClient + GatewayRouteConfigClient *appplatform.GatewayRouteConfigsClient + MonitoringSettingsClient *appplatform.MonitoringSettingsClient + DeploymentsClient *appplatform.DeploymentsClient + ServicesClient *appplatform.ServicesClient + ServiceRegistryClient *appplatform.ServiceRegistriesClient + StoragesClient *appplatform.StoragesClient } func NewClient(o *common.ClientOptions) *Client { apiPortalClient := appplatform.NewAPIPortalsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&apiPortalClient.Client, o.ResourceManagerAuthorizer) + apiPortalCustomDomainClient := appplatform.NewAPIPortalCustomDomainsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&apiPortalCustomDomainClient.Client, o.ResourceManagerAuthorizer) + appsClient := appplatform.NewAppsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&appsClient.Client, o.ResourceManagerAuthorizer) @@ -78,22 +82,23 @@ func NewClient(o *common.ClientOptions) *Client { o.ConfigureClient(&storageClient.Client, o.ResourceManagerAuthorizer) return &Client{ - APIPortalClient: &apiPortalClient, - AppsClient: &appsClient, - BindingsClient: &bindingsClient, - BuildPackBindingClient: &buildpackBindingClient, - BuildServiceBuilderClient: &buildServiceBuilderClient, - CertificatesClient: &certificatesClient, - ConfigServersClient: &configServersClient, - ConfigurationServiceClient: &configurationServiceClient, - CustomDomainsClient: &customDomainsClient, - DeploymentsClient: &deploymentsClient, - GatewayClient: &gatewayClient, - GatewayCustomDomainClient: &gatewayCustomDomainClient, - GatewayRouteConfigClient: &gatewayRouteConfigClient, - MonitoringSettingsClient: &monitoringSettingsClient, - ServicesClient: &servicesClient, - ServiceRegistryClient: &serviceRegistryClient, - StoragesClient: &storageClient, + APIPortalClient: &apiPortalClient, + APIPortalCustomDomainClient: &apiPortalCustomDomainClient, + AppsClient: &appsClient, + BindingsClient: &bindingsClient, + BuildPackBindingClient: &buildpackBindingClient, + BuildServiceBuilderClient: &buildServiceBuilderClient, + CertificatesClient: &certificatesClient, + ConfigServersClient: &configServersClient, + ConfigurationServiceClient: &configurationServiceClient, + CustomDomainsClient: &customDomainsClient, + DeploymentsClient: &deploymentsClient, + GatewayClient: &gatewayClient, + GatewayCustomDomainClient: &gatewayCustomDomainClient, + GatewayRouteConfigClient: &gatewayRouteConfigClient, + MonitoringSettingsClient: &monitoringSettingsClient, + ServicesClient: &servicesClient, + ServiceRegistryClient: &serviceRegistryClient, + StoragesClient: &storageClient, } } diff --git a/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go b/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go new file mode 100644 index 000000000000..37faf35c4391 --- /dev/null +++ b/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go @@ -0,0 +1,81 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +type SpringCloudAPIPortalCustomDomainId struct { + SubscriptionId string + ResourceGroup string + SpringName string + ApiPortalName string + DomainName string +} + +func NewSpringCloudAPIPortalCustomDomainID(subscriptionId, resourceGroup, springName, apiPortalName, domainName string) SpringCloudAPIPortalCustomDomainId { + return SpringCloudAPIPortalCustomDomainId{ + SubscriptionId: subscriptionId, + ResourceGroup: resourceGroup, + SpringName: springName, + ApiPortalName: apiPortalName, + DomainName: domainName, + } +} + +func (id SpringCloudAPIPortalCustomDomainId) String() string { + segments := []string{ + fmt.Sprintf("Domain Name %q", id.DomainName), + fmt.Sprintf("Api Portal Name %q", id.ApiPortalName), + fmt.Sprintf("Spring Name %q", id.SpringName), + fmt.Sprintf("Resource Group %q", id.ResourceGroup), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "Spring Cloud API Portal Custom Domain", segmentsStr) +} + +func (id SpringCloudAPIPortalCustomDomainId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.AppPlatform/Spring/%s/apiPortals/%s/domains/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.SpringName, id.ApiPortalName, id.DomainName) +} + +// SpringCloudAPIPortalCustomDomainID parses a SpringCloudAPIPortalCustomDomain ID into an SpringCloudAPIPortalCustomDomainId struct +func SpringCloudAPIPortalCustomDomainID(input string) (*SpringCloudAPIPortalCustomDomainId, error) { + id, err := resourceids.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := SpringCloudAPIPortalCustomDomainId{ + SubscriptionId: id.SubscriptionID, + ResourceGroup: id.ResourceGroup, + } + + if resourceId.SubscriptionId == "" { + return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + } + + if resourceId.ResourceGroup == "" { + return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + } + + if resourceId.SpringName, err = id.PopSegment("Spring"); err != nil { + return nil, err + } + if resourceId.ApiPortalName, err = id.PopSegment("apiPortals"); err != nil { + return nil, err + } + if resourceId.DomainName, err = id.PopSegment("domains"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain_test.go b/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain_test.go new file mode 100644 index 000000000000..4e15e624ae1e --- /dev/null +++ b/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain_test.go @@ -0,0 +1,144 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.Id = SpringCloudAPIPortalCustomDomainId{} + +func TestSpringCloudAPIPortalCustomDomainIDFormatter(t *testing.T) { + actual := NewSpringCloudAPIPortalCustomDomainID("12345678-1234-9876-4563-123456789012", "resourceGroup1", "service1", "apiPortal1", "domain1").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/domains/domain1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestSpringCloudAPIPortalCustomDomainID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *SpringCloudAPIPortalCustomDomainId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Error: true, + }, + + { + // missing SpringName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/", + Error: true, + }, + + { + // missing value for SpringName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/", + Error: true, + }, + + { + // missing ApiPortalName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/", + Error: true, + }, + + { + // missing value for ApiPortalName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/", + Error: true, + }, + + { + // missing DomainName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/", + Error: true, + }, + + { + // missing value for DomainName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/domains/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/domains/domain1", + Expected: &SpringCloudAPIPortalCustomDomainId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroup: "resourceGroup1", + SpringName: "service1", + ApiPortalName: "apiPortal1", + DomainName: "domain1", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESOURCEGROUP1/PROVIDERS/MICROSOFT.APPPLATFORM/SPRING/SERVICE1/APIPORTALS/APIPORTAL1/DOMAINS/DOMAIN1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := SpringCloudAPIPortalCustomDomainID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.SpringName != v.Expected.SpringName { + t.Fatalf("Expected %q but got %q for SpringName", v.Expected.SpringName, actual.SpringName) + } + if actual.ApiPortalName != v.Expected.ApiPortalName { + t.Fatalf("Expected %q but got %q for ApiPortalName", v.Expected.ApiPortalName, actual.ApiPortalName) + } + if actual.DomainName != v.Expected.DomainName { + t.Fatalf("Expected %q but got %q for DomainName", v.Expected.DomainName, actual.DomainName) + } + } +} diff --git a/internal/services/springcloud/registration.go b/internal/services/springcloud/registration.go index fdb6cc476ccf..f308b8aaa5a1 100644 --- a/internal/services/springcloud/registration.go +++ b/internal/services/springcloud/registration.go @@ -38,6 +38,7 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{ "azurerm_spring_cloud_active_deployment": resourceSpringCloudActiveDeployment(), "azurerm_spring_cloud_api_portal": resourceSpringCloudAPIPortal(), + "azurerm_spring_cloud_api_portal_custom_domain": resourceSpringCloudAPIPortalCustomDomain(), "azurerm_spring_cloud_app": resourceSpringCloudApp(), "azurerm_spring_cloud_app_cosmosdb_association": resourceSpringCloudAppCosmosDBAssociation(), "azurerm_spring_cloud_app_mysql_association": resourceSpringCloudAppMysqlAssociation(), diff --git a/internal/services/springcloud/resourceids.go b/internal/services/springcloud/resourceids.go index c3a5a08605a9..ad9d0fecb1b4 100644 --- a/internal/services/springcloud/resourceids.go +++ b/internal/services/springcloud/resourceids.go @@ -3,6 +3,7 @@ package springcloud //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SpringCloudApp -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.AppPlatform/Spring/spring1/apps/app1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SpringCloudAppAssociation -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.AppPlatform/Spring/spring1/apps/app1/bindings/bind1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SpringCloudAPIPortal -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1 +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SpringCloudAPIPortalCustomDomain -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/domains/domain1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SpringCloudBuildServiceBuilder -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/buildServices/buildService1/builders/builder1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SpringCloudBuildPackBinding -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/buildServices/buildService1/builders/builder1/buildpackBindings/buildpackBinding1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SpringCloudDeployment -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.AppPlatform/Spring/spring1/apps/app1/deployments/deploy1 diff --git a/internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource.go b/internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource.go new file mode 100644 index 000000000000..6c0489982934 --- /dev/null +++ b/internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource.go @@ -0,0 +1,146 @@ +package springcloud + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/appplatform/mgmt/2022-03-01-preview/appplatform" + "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/springcloud/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/springcloud/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func resourceSpringCloudAPIPortalCustomDomain() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceSpringCloudAPIPortalCustomDomainCreateUpdate, + Read: resourceSpringCloudAPIPortalCustomDomainRead, + Update: resourceSpringCloudAPIPortalCustomDomainCreateUpdate, + Delete: resourceSpringCloudAPIPortalCustomDomainDelete, + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(30 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.SpringCloudAPIPortalCustomDomainID(id) + return err + }), + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + + "spring_cloud_api_portal_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.SpringCloudAPIPortalID, + }, + + "thumbprint": { + Type: pluginsdk.TypeString, + Optional: true, + }, + }, + } +} +func resourceSpringCloudAPIPortalCustomDomainCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + client := meta.(*clients.Client).AppPlatform.APIPortalCustomDomainClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + portalId, err := parse.SpringCloudAPIPortalID(d.Get("spring_cloud_api_portal_id").(string)) + if err != nil { + return err + } + id := parse.NewSpringCloudAPIPortalCustomDomainID(subscriptionId, portalId.ResourceGroup, portalId.SpringName, portalId.ApiPortalName, d.Get("name").(string)) + + if d.IsNewResource() { + existing, err := client.Get(ctx, id.ResourceGroup, id.SpringName, id.ApiPortalName, id.DomainName) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for existing %s: %+v", id, err) + } + } + if !utils.ResponseWasNotFound(existing.Response) { + return tf.ImportAsExistsError("azurerm_spring_cloud_api_portal_custom_domain", id.ID()) + } + } + + apiPortalCustomDomainResource := appplatform.APIPortalCustomDomainResource{ + Properties: &appplatform.APIPortalCustomDomainProperties{ + Thumbprint: utils.String(d.Get("thumbprint").(string)), + }, + } + future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.SpringName, id.ApiPortalName, id.DomainName, apiPortalCustomDomainResource) + if err != nil { + return fmt.Errorf("creating/updating %s: %+v", id, err) + } + + if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for creation/update of %s: %+v", id, err) + } + + d.SetId(id.ID()) + return resourceSpringCloudAPIPortalCustomDomainRead(d, meta) +} + +func resourceSpringCloudAPIPortalCustomDomainRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).AppPlatform.APIPortalCustomDomainClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.SpringCloudAPIPortalCustomDomainID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.SpringName, id.ApiPortalName, id.DomainName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] appplatform %q does not exist - removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("retrieving %s: %+v", id, err) + } + d.Set("name", id.DomainName) + d.Set("spring_cloud_api_portal_id", parse.NewSpringCloudAPIPortalID(id.SubscriptionId, id.ResourceGroup, id.SpringName, id.ApiPortalName).ID()) + if props := resp.Properties; props != nil { + d.Set("thumbprint", props.Thumbprint) + } + return nil +} + +func resourceSpringCloudAPIPortalCustomDomainDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).AppPlatform.APIPortalCustomDomainClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.SpringCloudAPIPortalCustomDomainID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ResourceGroup, id.SpringName, id.ApiPortalName, id.DomainName) + if err != nil { + return fmt.Errorf("deleting %s: %+v", id, err) + } + + if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for deletion of %s: %+v", id, err) + } + return nil +} diff --git a/internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource_test.go b/internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource_test.go new file mode 100644 index 000000000000..08b4ca741c79 --- /dev/null +++ b/internal/services/springcloud/spring_cloud_api_portal_custom_domain_resource_test.go @@ -0,0 +1,109 @@ +package springcloud_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/springcloud/parse" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type SpringCloudAPIPortalCustomDomainResource struct{} + +func TestAccSpringCloudAPIPortalCustomDomain_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_spring_cloud_api_portal_custom_domain", "test") + r := SpringCloudAPIPortalCustomDomainResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccSpringCloudAPIPortalCustomDomain_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_spring_cloud_api_portal_custom_domain", "test") + r := SpringCloudAPIPortalCustomDomainResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func (r SpringCloudAPIPortalCustomDomainResource) Exists(ctx context.Context, client *clients.Client, state *terraform.InstanceState) (*bool, error) { + id, err := parse.SpringCloudAPIPortalCustomDomainID(state.ID) + if err != nil { + return nil, err + } + resp, err := client.AppPlatform.APIPortalCustomDomainClient.Get(ctx, id.ResourceGroup, id.SpringName, id.ApiPortalName, id.DomainName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return utils.Bool(false), nil + } + return nil, fmt.Errorf("retrieving %s: %+v", id, err) + } + return utils.Bool(true), nil +} + +func (r SpringCloudAPIPortalCustomDomainResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-spring-%[2]d" + location = "%[1]s" +} + +resource "azurerm_spring_cloud_service" "test" { + name = "acctest-sc-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "E0" +} + +resource "azurerm_spring_cloud_api_portal" "test" { + name = "default" + spring_cloud_service_id = azurerm_spring_cloud_service.test.id +} +`, data.Locations.Primary, data.RandomInteger) +} + +func (r SpringCloudAPIPortalCustomDomainResource) basic(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_spring_cloud_api_portal_custom_domain" "test" { + name = "${azurerm_spring_cloud_service.test.name}.azuremicroservices.io" + spring_cloud_api_portal_id = azurerm_spring_cloud_api_portal.test.id +} +`, template) +} + +func (r SpringCloudAPIPortalCustomDomainResource) requiresImport(data acceptance.TestData) string { + config := r.basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_spring_cloud_api_portal_custom_domain" "import" { + name = azurerm_spring_cloud_api_portal_custom_domain.test.name + spring_cloud_api_portal_id = azurerm_spring_cloud_api_portal_custom_domain.test.spring_cloud_api_portal_id +} +`, config) +} diff --git a/internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id.go b/internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id.go new file mode 100644 index 000000000000..e29bac42840e --- /dev/null +++ b/internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id.go @@ -0,0 +1,23 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + + "github.com/hashicorp/terraform-provider-azurerm/internal/services/springcloud/parse" +) + +func SpringCloudAPIPortalCustomDomainID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := parse.SpringCloudAPIPortalCustomDomainID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id_test.go b/internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id_test.go new file mode 100644 index 000000000000..ba357d758d9c --- /dev/null +++ b/internal/services/springcloud/validate/spring_cloud_api_portal_custom_domain_id_test.go @@ -0,0 +1,100 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestSpringCloudAPIPortalCustomDomainID(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + + { + // empty + Input: "", + Valid: false, + }, + + { + // missing SubscriptionId + Input: "/", + Valid: false, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Valid: false, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Valid: false, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Valid: false, + }, + + { + // missing SpringName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/", + Valid: false, + }, + + { + // missing value for SpringName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/", + Valid: false, + }, + + { + // missing ApiPortalName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/", + Valid: false, + }, + + { + // missing value for ApiPortalName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/", + Valid: false, + }, + + { + // missing DomainName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/", + Valid: false, + }, + + { + // missing value for DomainName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/domains/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/domains/domain1", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESOURCEGROUP1/PROVIDERS/MICROSOFT.APPPLATFORM/SPRING/SERVICE1/APIPORTALS/APIPORTAL1/DOMAINS/DOMAIN1", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := SpringCloudAPIPortalCustomDomainID(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} diff --git a/website/docs/r/spring_cloud_api_portal_custom_domain.html.markdown b/website/docs/r/spring_cloud_api_portal_custom_domain.html.markdown new file mode 100644 index 000000000000..5a486bde43ec --- /dev/null +++ b/website/docs/r/spring_cloud_api_portal_custom_domain.html.markdown @@ -0,0 +1,82 @@ +--- +subcategory: "Spring Cloud" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_spring_cloud_api_portal_custom_domain" +description: |- + Manages a Spring Cloud API Portal Domain. +--- + +# azurerm_spring_cloud_api_portal_custom_domain + +Manages a Spring Cloud API Portal Domain. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_spring_cloud_service" "example" { + name = "example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + sku_name = "E0" +} + +resource "azurerm_spring_cloud_gateway" "example" { + name = "default" + spring_cloud_service_id = azurerm_spring_cloud_service.example.id +} + +resource "azurerm_spring_cloud_api_portal" "example" { + name = "default" + spring_cloud_service_id = azurerm_spring_cloud_service.example.id + gateway_ids = [azurerm_spring_cloud_gateway.example.id] +} + +resource "azurerm_spring_cloud_api_portal_custom_domain" "example" { + name = "example.com" + spring_cloud_api_portal_id = azurerm_spring_cloud_api_portal.example.id +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name which should be used for this Spring Cloud API Portal Domain. Changing this forces a new Spring Cloud API Portal Domain to be created. + +* `spring_cloud_api_portal_id` - (Required) The ID of the Spring Cloud API Portal. Changing this forces a new Spring Cloud API Portal Domain to be created. + +--- + +* `thumbprint` - (Optional) Specifies the thumbprint of the Spring Cloud Certificate that binds to the Spring Cloud API Portal Domain. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Spring Cloud API Portal Domain. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Spring Cloud API Portal Domain. +* `read` - (Defaults to 5 minutes) Used when retrieving the Spring Cloud API Portal Domain. +* `update` - (Defaults to 30 minutes) Used when updating the Spring Cloud API Portal Domain. +* `delete` - (Defaults to 30 minutes) Used when deleting the Spring Cloud API Portal Domain. + +## Import + +Spring Cloud API Portal Domains can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_spring_cloud_api_portal_custom_domain.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.AppPlatform/Spring/service1/apiPortals/apiPortal1/domains/domain1 +``` From c30730f055fab593e42e6e0a47aa030db1124b90 Mon Sep 17 00:00:00 2001 From: Heng Lu Date: Thu, 26 May 2022 14:16:16 +0800 Subject: [PATCH 2/2] fix gogen --- .../springcloud/parse/spring_cloud_api_portal_custom_domain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go b/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go index 37faf35c4391..d06955e0f611 100644 --- a/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go +++ b/internal/services/springcloud/parse/spring_cloud_api_portal_custom_domain.go @@ -35,7 +35,7 @@ func (id SpringCloudAPIPortalCustomDomainId) String() string { fmt.Sprintf("Resource Group %q", id.ResourceGroup), } segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Spring Cloud API Portal Custom Domain", segmentsStr) + return fmt.Sprintf("%s: (%s)", "Spring Cloud A P I Portal Custom Domain", segmentsStr) } func (id SpringCloudAPIPortalCustomDomainId) ID() string {