diff --git a/azurerm/internal/services/databasemigration/client/client.go b/azurerm/internal/services/databasemigration/client/client.go index e15f08de5b57..90dba0b7f494 100644 --- a/azurerm/internal/services/databasemigration/client/client.go +++ b/azurerm/internal/services/databasemigration/client/client.go @@ -7,12 +7,18 @@ import ( type Client struct { ServicesClient *datamigration.ServicesClient + ProjectsClient *datamigration.ProjectsClient } func NewClient(o *common.ClientOptions) *Client { servicesClient := datamigration.NewServicesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&servicesClient.Client, o.ResourceManagerAuthorizer) + + projectsClient := datamigration.NewProjectsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&projectsClient.Client, o.ResourceManagerAuthorizer) + return &Client{ ServicesClient: &servicesClient, + ProjectsClient: &projectsClient, } } diff --git a/azurerm/internal/services/databasemigration/data_source_database_migration_project.go b/azurerm/internal/services/databasemigration/data_source_database_migration_project.go new file mode 100644 index 000000000000..ad7aed0b9253 --- /dev/null +++ b/azurerm/internal/services/databasemigration/data_source_database_migration_project.go @@ -0,0 +1,91 @@ +package databasemigration + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmDatabaseMigrationProject() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmDatabaseMigrationProjectRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateDatabaseMigrationProjectName, + }, + + "service_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateDatabaseMigrationServiceName, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + + "source_platform": { + Type: schema.TypeString, + Computed: true, + }, + + "target_platform": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} + +func dataSourceArmDatabaseMigrationProjectRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DatabaseMigration.ProjectsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + serviceName := d.Get("service_name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, serviceName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Database Migration Project (Project Name %q / Service Name %q / Group Name %q) was not found", name, serviceName, resourceGroup) + } + return fmt.Errorf("Error reading Database Migration Project (Project Name %q / Service Name %q / Group Name %q): %+v", name, serviceName, resourceGroup, err) + } + + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("Cannot read Database Migration Project (Project Name %q / Service Name %q / Group Name %q) ID", name, serviceName, resourceGroup) + } + d.SetId(*resp.ID) + + d.Set("resource_group_name", resourceGroup) + + location := "" + if resp.Location != nil { + location = azure.NormalizeLocation(*resp.Location) + } + d.Set("location", location) + + if prop := resp.ProjectProperties; prop != nil { + d.Set("source_platform", string(prop.SourcePlatform)) + d.Set("target_platform", string(prop.TargetPlatform)) + } + + return nil +} diff --git a/azurerm/internal/services/databasemigration/data_source_database_migration_service.go b/azurerm/internal/services/databasemigration/data_source_database_migration_service.go index 076c12d92369..515b9b1f9dc1 100644 --- a/azurerm/internal/services/databasemigration/data_source_database_migration_service.go +++ b/azurerm/internal/services/databasemigration/data_source_database_migration_service.go @@ -25,7 +25,7 @@ func dataSourceArmDatabaseMigrationService() *schema.Resource { "name": { Type: schema.TypeString, Required: true, - ValidateFunc: validateDatabasesMigrationServiceName, + ValidateFunc: validateDatabaseMigrationServiceName, }, "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), diff --git a/azurerm/internal/services/databasemigration/parse/datamigration_project.go b/azurerm/internal/services/databasemigration/parse/datamigration_project.go new file mode 100644 index 000000000000..d047ab962f44 --- /dev/null +++ b/azurerm/internal/services/databasemigration/parse/datamigration_project.go @@ -0,0 +1,38 @@ +package parse + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type DatabaseMigrationProjectId struct { + ResourceGroup string + Service string + Name string +} + +func DatabaseMigrationProjectID(input string) (*DatabaseMigrationProjectId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, fmt.Errorf("[ERROR] Unable to parse Database Migration Project ID %q: %+v", input, err) + } + + project := DatabaseMigrationProjectId{ + ResourceGroup: id.ResourceGroup, + } + + if project.Service, err = id.PopSegment("services"); err != nil { + return nil, err + } + + if project.Name, err = id.PopSegment("projects"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &project, nil +} diff --git a/azurerm/internal/services/databasemigration/parse/datamigration_project_test.go b/azurerm/internal/services/databasemigration/parse/datamigration_project_test.go new file mode 100644 index 000000000000..53b0505fd01c --- /dev/null +++ b/azurerm/internal/services/databasemigration/parse/datamigration_project_test.go @@ -0,0 +1,89 @@ +package parse + +import ( + "testing" +) + +func TestDatabaseMigrationProjectID(t *testing.T) { + testData := []struct { + Name string + Input string + Error bool + Expect *DatabaseMigrationProjectId + }{ + { + Name: "Empty", + Input: "", + Error: true, + }, + { + Name: "No Resource Groups Segment", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000", + Error: true, + }, + { + Name: "No Resource Groups Value", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/", + Error: true, + }, + { + Name: "No Resource Group ID", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo/", + Error: true, + }, + { + Name: "Missing service name", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/services", + Error: true, + }, + { + Name: "No Projects Segment", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/services/service1", + Error: true, + }, + { + Name: "Missing project name", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/services/service1/projects", + Error: true, + }, + { + Name: "Service name", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.Datamigration/services/service1/projects/project1", + Expect: &DatabaseMigrationProjectId{ + ResourceGroup: "resGroup1", + Service: "service1", + Name: "project1", + }, + }, + { + Name: "Wrong Casing", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.Datamigration/Services/service1/projects/project1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Name) + + actual, err := DatabaseMigrationProjectID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expected a value but got an error: %s", err) + } + + if actual.ResourceGroup != v.Expect.ResourceGroup { + t.Fatalf("Expected %q but got %q for Resource Group", v.Expect.ResourceGroup, actual.ResourceGroup) + } + + if actual.Service != v.Expect.Service { + t.Fatalf("Expected %q but got %q for Service", v.Expect.Service, actual.Service) + } + + if actual.Name != v.Expect.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expect.Name, actual.Name) + } + } +} diff --git a/azurerm/internal/services/databasemigration/registration.go b/azurerm/internal/services/databasemigration/registration.go index 9a41c8047e65..7a2c32aae2a3 100644 --- a/azurerm/internal/services/databasemigration/registration.go +++ b/azurerm/internal/services/databasemigration/registration.go @@ -22,6 +22,7 @@ func (r Registration) WebsiteCategories() []string { func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ "azurerm_database_migration_service": dataSourceArmDatabaseMigrationService(), + "azurerm_database_migration_project": dataSourceArmDatabaseMigrationProject(), } } @@ -29,6 +30,7 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { func (r Registration) SupportedResources() map[string]*schema.Resource { resources := map[string]*schema.Resource{ "azurerm_database_migration_service": resourceArmDatabaseMigrationService(), + "azurerm_database_migration_project": resourceArmDatabaseMigrationProject(), } return resources diff --git a/azurerm/internal/services/databasemigration/resource_arm_database_migration_project.go b/azurerm/internal/services/databasemigration/resource_arm_database_migration_project.go new file mode 100644 index 000000000000..137ce4d6188a --- /dev/null +++ b/azurerm/internal/services/databasemigration/resource_arm_database_migration_project.go @@ -0,0 +1,190 @@ +package databasemigration + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/datamigration/mgmt/2018-04-19/datamigration" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/databasemigration/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmDatabaseMigrationProject() *schema.Resource { + return &schema.Resource{ + Create: resourceArmDatabaseMigrationProjectCreateUpdate, + Read: resourceArmDatabaseMigrationProjectRead, + Update: resourceArmDatabaseMigrationProjectCreateUpdate, + Delete: resourceArmDatabaseMigrationProjectDelete, + + Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { + _, err := parse.DatabaseMigrationProjectID(id) + return err + }), + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateDatabaseMigrationProjectName, + }, + + "service_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateDatabaseMigrationServiceName, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "source_platform": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // Now that go sdk only export SQL as source platform type, we only allow it here. + string(datamigration.ProjectSourcePlatformSQL), + }, false), + }, + + "target_platform": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // Now that go sdk only export SQL as source platform type, we only allow it here. + string(datamigration.ProjectTargetPlatformSQLDB), + }, false), + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmDatabaseMigrationProjectCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DatabaseMigration.ProjectsClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + serviceName := d.Get("service_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, serviceName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for present of existing Database Migration Project (Project Name: %q / Service Name %q / Group Name %q): %+v", name, serviceName, resourceGroup, err) + } + } + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_database_migration_project", *existing.ID) + } + } + + location := azure.NormalizeLocation(d.Get("location").(string)) + sourcePlatform := d.Get("source_platform").(string) + targetPlatform := d.Get("target_platform").(string) + t := d.Get("tags").(map[string]interface{}) + + parameters := datamigration.Project{ + Location: utils.String(location), + ProjectProperties: &datamigration.ProjectProperties{ + SourcePlatform: datamigration.ProjectSourcePlatform(sourcePlatform), + TargetPlatform: datamigration.ProjectTargetPlatform(targetPlatform), + }, + Tags: tags.Expand(t), + } + + if _, err := client.CreateOrUpdate(ctx, parameters, resourceGroup, serviceName, name); err != nil { + return fmt.Errorf("Error creating Database Migration Project (Project Name %q / Service Name %q / Group Name %q): %+v", name, serviceName, resourceGroup, err) + } + + resp, err := client.Get(ctx, resourceGroup, serviceName, name) + if err != nil { + return fmt.Errorf("Error retrieving Database Migration Project (Project Name %q / Service Name %q / Group Name %q): %+v", name, serviceName, resourceGroup, err) + } + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("Cannot read Database Migration Project (Project Name %q / Service Name %q / Group Name %q) ID", name, serviceName, resourceGroup) + } + d.SetId(*resp.ID) + + return resourceArmDatabaseMigrationProjectRead(d, meta) +} + +func resourceArmDatabaseMigrationProjectRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DatabaseMigration.ProjectsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DatabaseMigrationProjectID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.Service, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] Database Migration Project %q does not exist - removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("Error reading Database Migration Project (Project Name %q / Service Name %q / Group Name %q): %+v", id.Name, id.Service, id.ResourceGroup, err) + } + + d.Set("name", resp.Name) + d.Set("service_name", id.Service) + d.Set("resource_group_name", id.ResourceGroup) + + location := "" + if resp.Location != nil { + location = azure.NormalizeLocation(*resp.Location) + } + d.Set("location", location) + + if prop := resp.ProjectProperties; prop != nil { + d.Set("source_platform", string(prop.SourcePlatform)) + d.Set("target_platform", string(prop.TargetPlatform)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmDatabaseMigrationProjectDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DatabaseMigration.ProjectsClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DatabaseMigrationProjectID(d.Id()) + if err != nil { + return err + } + + deleteRunningTasks := false + if _, err := client.Delete(ctx, id.ResourceGroup, id.Service, id.Name, &deleteRunningTasks); err != nil { + return fmt.Errorf("Error deleting Database Migration Project (Project Name %q / Service Name %q / Group Name %q): %+v", id.Name, id.Service, id.ResourceGroup, err) + } + + return nil +} diff --git a/azurerm/internal/services/databasemigration/resource_arm_database_migration_service.go b/azurerm/internal/services/databasemigration/resource_arm_database_migration_service.go index 2f5457d74e02..4fb27f013f6f 100644 --- a/azurerm/internal/services/databasemigration/resource_arm_database_migration_service.go +++ b/azurerm/internal/services/databasemigration/resource_arm_database_migration_service.go @@ -45,7 +45,7 @@ func resourceArmDatabaseMigrationService() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validateDatabasesMigrationServiceName, + ValidateFunc: validateDatabaseMigrationServiceName, }, "location": azure.SchemaLocation(), diff --git a/azurerm/internal/services/databasemigration/tests/data_source_database_migration_project_test.go b/azurerm/internal/services/databasemigration/tests/data_source_database_migration_project_test.go new file mode 100644 index 000000000000..cf3f20fcf62d --- /dev/null +++ b/azurerm/internal/services/databasemigration/tests/data_source_database_migration_project_test.go @@ -0,0 +1,40 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccDataSourceAzureRMDatabaseMigrationProject_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_database_migration_project", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceDatabaseMigrationProject_basic(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(data.ResourceName, "source_platform", "SQL"), + resource.TestCheckResourceAttr(data.ResourceName, "target_platform", "SQLDB"), + ), + }, + }, + }) +} + +func testAccDataSourceDatabaseMigrationProject_basic(data acceptance.TestData) string { + config := testAccAzureRMDatabaseMigrationProject_basic(data) + return fmt.Sprintf(` +%s + +data "azurerm_database_migration_project" "test" { + name = azurerm_database_migration_project.test.name + service_name = azurerm_database_migration_project.test.service_name + resource_group_name = azurerm_database_migration_project.test.resource_group_name +} +`, config) +} diff --git a/azurerm/internal/services/databasemigration/tests/resource_arm_database_migration_project_test.go b/azurerm/internal/services/databasemigration/tests/resource_arm_database_migration_project_test.go new file mode 100644 index 000000000000..1324a9992fe6 --- /dev/null +++ b/azurerm/internal/services/databasemigration/tests/resource_arm_database_migration_project_test.go @@ -0,0 +1,216 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/databasemigration/parse" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMDatabaseMigrationProject_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_database_migration_project", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMDatabaseMigrationProjectDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMDatabaseMigrationProject_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDatabaseMigrationProjectExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "source_platform", "SQL"), + resource.TestCheckResourceAttr(data.ResourceName, "target_platform", "SQLDB"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMDatabaseMigrationProject_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_database_migration_project", "test") + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMDatabaseMigrationProjectDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMDatabaseMigrationProject_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDatabaseMigrationProjectExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "source_platform", "SQL"), + resource.TestCheckResourceAttr(data.ResourceName, "target_platform", "SQLDB"), + resource.TestCheckResourceAttr(data.ResourceName, "tags.name", "Test"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMDatabaseMigrationProject_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + data := acceptance.BuildTestData(t, "azurerm_database_migration_project", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMDatabaseMigrationProjectDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMDatabaseMigrationProject_basic(data), + }, + data.RequiresImportErrorStep(testAccAzureRMDatabaseMigrationProject_requiresImport), + }, + }) +} + +func TestAccAzureRMDatabaseMigrationProject_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_database_migration_project", "test") + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMDatabaseMigrationProjectDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMDatabaseMigrationProject_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDatabaseMigrationProjectExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMDatabaseMigrationProject_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDatabaseMigrationProjectExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "tags.name", "Test"), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMDatabaseMigrationProject_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDatabaseMigrationProjectExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMDatabaseMigrationProjectExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Database Migration Project not found: %s", resourceName) + } + + id, err := parse.DatabaseMigrationProjectID(rs.Primary.ID) + if err != nil { + return err + } + + client := acceptance.AzureProvider.Meta().(*clients.Client).DatabaseMigration.ProjectsClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + if resp, err := client.Get(ctx, id.ResourceGroup, id.Service, id.Name); err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Database Migration Project (Project Name %q / Service Name %q / Group Name %q) does not exist", id.Name, id.Service, id.ResourceGroup) + } + return fmt.Errorf("Bad: Get on ProjectsClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMDatabaseMigrationProjectDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).DatabaseMigration.ProjectsClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_database_migration_project" { + continue + } + + id, err := parse.DatabaseMigrationProjectID(rs.Primary.ID) + if err != nil { + return err + } + + if resp, err := client.Get(ctx, id.ResourceGroup, id.Service, id.Name); err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Get on ProjectsClient: %+v", err) + } + } + + return nil + } + + return nil +} + +func testAccAzureRMDatabaseMigrationProject_basic(data acceptance.TestData) string { + template := testAccAzureRMDatabaseMigrationService_basic(data) + + return fmt.Sprintf(` +%s + +resource "azurerm_database_migration_project" "test" { + name = "acctestDbmsProject-%d" + service_name = azurerm_database_migration_service.test.name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + source_platform = "SQL" + target_platform = "SQLDB" +} +`, template, data.RandomInteger) +} + +func testAccAzureRMDatabaseMigrationProject_complete(data acceptance.TestData) string { + template := testAccAzureRMDatabaseMigrationService_basic(data) + + return fmt.Sprintf(` +%s + +resource "azurerm_database_migration_project" "test" { + name = "acctestDbmsProject-%d" + service_name = azurerm_database_migration_service.test.name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + source_platform = "SQL" + target_platform = "SQLDB" + tags = { + name = "Test" + } +} +`, template, data.RandomInteger) +} + +func testAccAzureRMDatabaseMigrationProject_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMDatabaseMigrationProject_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_database_migration_project" "import" { + name = azurerm_database_migration_project.test.name + service_name = azurerm_database_migration_project.test.service_name + resource_group_name = azurerm_database_migration_project.test.resource_group_name + location = azurerm_database_migration_project.test.location + source_platform = azurerm_database_migration_project.test.source_platform + target_platform = azurerm_database_migration_project.test.target_platform +} +`, template) +} diff --git a/azurerm/internal/services/databasemigration/validation.go b/azurerm/internal/services/databasemigration/validation.go index 0e325b3e67ab..025529197cc5 100644 --- a/azurerm/internal/services/databasemigration/validation.go +++ b/azurerm/internal/services/databasemigration/validation.go @@ -5,7 +5,19 @@ import ( "regexp" ) -func validateDatabasesMigrationServiceName(i interface{}, k string) ([]string, []error) { +func validateDatabaseMigrationServiceName(i interface{}, k string) ([]string, []error) { + v, ok := i.(string) + if !ok { + return nil, []error{fmt.Errorf("expected type of %q to be string", k)} + } + validName := regexp.MustCompile(`^[\d\w]+[\d\w\-_.]*$`) + if !validName.MatchString(v) { + return nil, []error{fmt.Errorf("invalid format of %q", k)} + } + return nil, nil +} + +func validateDatabaseMigrationProjectName(i interface{}, k string) ([]string, []error) { v, ok := i.(string) if !ok { return nil, []error{fmt.Errorf("expected type of %q to be string", k)} diff --git a/website/azurerm.erb b/website/azurerm.erb index 124f703c1f8d..b70ddc5137a4 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -162,6 +162,10 @@ azurerm_dns_zone +
  • + azurerm_database_migration_project +
  • +
  • azurerm_database_migration_service
  • @@ -1189,6 +1193,10 @@
  • Database Migration Resources