diff --git a/azurerm/internal/services/datafactory/data_factory_integration_runtime_self_hosted.go b/azurerm/internal/services/datafactory/data_factory_integration_runtime_self_hosted.go new file mode 100644 index 000000000000..f9bfa7618586 --- /dev/null +++ b/azurerm/internal/services/datafactory/data_factory_integration_runtime_self_hosted.go @@ -0,0 +1,276 @@ +package datafactory + +import ( + "bytes" + "fmt" + "regexp" + "time" + + "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "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/helpers/validate" + "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/datafactory/parse" + 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 resourceArmDataFactoryIntegrationRuntimeSelfHosted() *schema.Resource { + return &schema.Resource{ + Create: resourceArmDataFactoryIntegrationRuntimeSelfHostedCreateUpdate, + Read: resourceArmDataFactoryIntegrationRuntimeSelfHostedRead, + Update: resourceArmDataFactoryIntegrationRuntimeSelfHostedCreateUpdate, + Delete: resourceArmDataFactoryIntegrationRuntimeSelfHostedDelete, + + Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { + _, err := parse.DataFactoryIntegrationRuntimeID(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: validation.StringMatch( + regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), + `Invalid name for Self-Hosted Integration Runtime: minimum 3 characters, must start and end with a number or a letter, may only consist of letters, numbers and dashes and no consecutive dashes.`, + ), + }, + + "data_factory_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "description": { + Type: schema.TypeString, + Optional: true, + }, + + "rbac_authorization": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, + + "auth_key_1": { + Type: schema.TypeString, + Computed: true, + }, + + "auth_key_2": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceArmDataFactoryIntegrationRuntimeSelfHostedCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DataFactory.IntegrationRuntimesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + factoryName := d.Get("data_factory_name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, factoryName, name, "") + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Data Factory Self-Hosted Integration Runtime %q (Resource Group %q, Data Factory %q): %s", name, resourceGroup, factoryName, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_data_factory_integration_runtime_self_hosted", *existing.ID) + } + } + + description := d.Get("description").(string) + + selfHostedIntegrationRuntime := datafactory.SelfHostedIntegrationRuntime{ + Description: &description, + Type: datafactory.TypeSelfHosted, + } + + properties := expandAzureRmDataFactoryIntegrationRuntimeSelfHostedTypeProperties(d) + if properties != nil { + selfHostedIntegrationRuntime.SelfHostedIntegrationRuntimeTypeProperties = properties + } + + basicIntegrationRuntime, _ := selfHostedIntegrationRuntime.AsBasicIntegrationRuntime() + + integrationRuntime := datafactory.IntegrationRuntimeResource{ + Name: &name, + Properties: basicIntegrationRuntime, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, factoryName, name, integrationRuntime, ""); err != nil { + return fmt.Errorf("Error creating/updating Data Factory Self-Hosted Integration Runtime %q (Resource Group %q, Data Factory %q): %+v", name, resourceGroup, factoryName, err) + } + + resp, err := client.Get(ctx, resourceGroup, factoryName, name, "") + if err != nil { + return fmt.Errorf("Error retrieving Data Factory Self-Hosted Integration Runtime %q (Resource Group %q, Data Factory %q): %+v", name, resourceGroup, factoryName, err) + } + + if resp.ID == nil { + return fmt.Errorf("Cannot read Data Factory Self-Hosted Integration Runtime %q (Resource Group %q, Data Factory %q) ID", name, resourceGroup, factoryName) + } + + d.SetId(*resp.ID) + + return resourceArmDataFactoryIntegrationRuntimeSelfHostedRead(d, meta) +} + +func resourceArmDataFactoryIntegrationRuntimeSelfHostedRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DataFactory.IntegrationRuntimesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DataFactoryIntegrationRuntimeID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + factoryName := id.DataFactory + name := id.Name + + resp, err := client.Get(ctx, resourceGroup, factoryName, name, "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error retrieving Data Factory Self-Hosted Integration Runtime %q (Resource Group %q, Data Factory %q): %+v", name, resourceGroup, factoryName, err) + } + + d.Set("name", name) + d.Set("data_factory_name", factoryName) + d.Set("resource_group_name", resourceGroup) + + selfHostedIntegrationRuntime, convertSuccess := resp.Properties.AsSelfHostedIntegrationRuntime() + + if !convertSuccess { + return fmt.Errorf("Error converting integration runtime to Self-Hosted integration runtime %q (Resource Group %q, Data Factory %q)", name, resourceGroup, factoryName) + } + + if selfHostedIntegrationRuntime.Description != nil { + d.Set("description", selfHostedIntegrationRuntime.Description) + } + + if props := selfHostedIntegrationRuntime.SelfHostedIntegrationRuntimeTypeProperties; props != nil { + // LinkedInfo BasicLinkedIntegrationRuntimeType + if linkedInfo := props.LinkedInfo; linkedInfo != nil { + rbacAuthorization, _ := linkedInfo.AsLinkedIntegrationRuntimeRbacAuthorization() + if rbacAuthorization != nil { + if err := d.Set("rbac_authorization", schema.NewSet(resourceArmDataFactoryIntegrationRuntimeSelfHostedRbacAuthorizationHash, flattenAzureRmDataFactoryIntegrationRuntimeSelfHostedTypePropertiesRbacAuthorization(rbacAuthorization))); err != nil { + return fmt.Errorf("Error setting `rbac_authorization`: %#v", err) + } + } + } + return nil + } + + respKey, errKey := client.ListAuthKeys(ctx, resourceGroup, factoryName, name) + if errKey != nil { + if utils.ResponseWasNotFound(respKey.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error retrieving Data Factory Self-Hosted Integration Runtime %q Auth Keys (Resource Group %q, Data Factory %q): %+v", name, resourceGroup, factoryName, errKey) + } + + d.Set("auth_key_1", respKey.AuthKey1) + d.Set("auth_key_1", respKey.AuthKey2) + + return nil +} + +func resourceArmDataFactoryIntegrationRuntimeSelfHostedDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DataFactory.IntegrationRuntimesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DataFactoryIntegrationRuntimeID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + factoryName := id.DataFactory + name := id.Name + + response, err := client.Delete(ctx, resourceGroup, factoryName, name) + if err != nil { + if !utils.ResponseWasNotFound(response) { + return fmt.Errorf("Error deleting Data Factory SelfHosted Integration Runtime %q (Resource Group %q, Data Factory %q): %+v", name, resourceGroup, factoryName, err) + } + } + return nil +} + +func expandAzureRmDataFactoryIntegrationRuntimeSelfHostedTypeProperties(d *schema.ResourceData) *datafactory.SelfHostedIntegrationRuntimeTypeProperties { + if _, ok := d.GetOk("rbac_authorization"); ok { + rbacAuthorization := d.Get("rbac_authorization").(*schema.Set).List() + rbacConfig := rbacAuthorization[0].(map[string]interface{}) + rbac := rbacConfig["resource_id"].(string) + linkedInfo := &datafactory.SelfHostedIntegrationRuntimeTypeProperties{ + LinkedInfo: &datafactory.LinkedIntegrationRuntimeRbacAuthorization{ + ResourceID: &rbac, + AuthorizationType: datafactory.AuthorizationTypeRBAC, + }, + } + return linkedInfo + } + return nil +} + +func flattenAzureRmDataFactoryIntegrationRuntimeSelfHostedTypePropertiesRbacAuthorization(input *datafactory.LinkedIntegrationRuntimeRbacAuthorization) []interface{} { + result := make(map[string]interface{}) + result["resource_id"] = *input.ResourceID + + return []interface{}{result} +} + +func resourceArmDataFactoryIntegrationRuntimeSelfHostedRbacAuthorizationHash(v interface{}) int { + var buf bytes.Buffer + + if m, ok := v.(map[string]interface{}); ok { + if v, ok := m["resource_id"]; ok { + buf.WriteString(fmt.Sprintf("%s-", v.(string))) + } + } + + return hashcode.String(buf.String()) +} diff --git a/azurerm/internal/services/datafactory/parse/data_factory_integration_runtime.go b/azurerm/internal/services/datafactory/parse/data_factory_integration_runtime.go new file mode 100644 index 000000000000..3b6ab1d16e5c --- /dev/null +++ b/azurerm/internal/services/datafactory/parse/data_factory_integration_runtime.go @@ -0,0 +1,34 @@ +package parse + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type DataFactoryIntegrationRuntimeId struct { + ResourceGroup string + Name string + DataFactory string +} + +func DataFactoryIntegrationRuntimeID(input string) (*DataFactoryIntegrationRuntimeId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, fmt.Errorf("[ERROR] Unable to parse Data Factory Integration Runtime ID %q: %+v", input, err) + } + + dataFactoryIntegrationRuntime := DataFactoryIntegrationRuntimeId{ + ResourceGroup: id.ResourceGroup, + } + + if dataFactoryIntegrationRuntime.DataFactory, err = id.PopSegment("factories"); err != nil { + return nil, err + } + + if dataFactoryIntegrationRuntime.Name, err = id.PopSegment("integrationruntimes"); err != nil { + return nil, err + } + + return &dataFactoryIntegrationRuntime, nil +} diff --git a/azurerm/internal/services/datafactory/parse/data_factory_integration_runtime_test.go b/azurerm/internal/services/datafactory/parse/data_factory_integration_runtime_test.go new file mode 100644 index 000000000000..2be0460f7030 --- /dev/null +++ b/azurerm/internal/services/datafactory/parse/data_factory_integration_runtime_test.go @@ -0,0 +1,61 @@ +package parse + +import "testing" + +func TestParseDataFactoryIntegrationRuntimeID(t *testing.T) { + testData := []struct { + Name string + Input string + Expected *DataFactoryIntegrationRuntimeId + }{ + { + Name: "Empty", + Input: "", + Expected: nil, + }, + { + Name: "No Data Factory segment", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/", + Expected: nil, + }, + { + Name: "No Integration Runtime name", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/Microsoft.DataFactory/factories/factory1/integrationruntimes/", + Expected: nil, + }, + { + Name: "Case incorrect in path element", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/microsoft.dataFactory/factories/factory1/Integrationruntimes/integrationRuntimeName", + Expected: nil, + }, + { + Name: "Valid", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/Microsoft.DataFactory/factories/factory1/integrationruntimes/integrationRuntimeName", + Expected: &DataFactoryIntegrationRuntimeId{ + ResourceGroup: "myGroup1", + Name: "integrationRuntimeName", + DataFactory: "factory1", + }, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Name) + + actual, err := DataFactoryIntegrationRuntimeID(v.Input) + if err != nil { + if v.Expected == nil { + continue + } + + t.Fatalf("Expected a value but got an error: %s", err) + } + + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + } +} diff --git a/azurerm/internal/services/datafactory/registration.go b/azurerm/internal/services/datafactory/registration.go index d2bbd410756f..8cccada9364b 100644 --- a/azurerm/internal/services/datafactory/registration.go +++ b/azurerm/internal/services/datafactory/registration.go @@ -33,6 +33,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_data_factory_dataset_postgresql": resourceArmDataFactoryDatasetPostgreSQL(), "azurerm_data_factory_dataset_sql_server_table": resourceArmDataFactoryDatasetSQLServerTable(), "azurerm_data_factory_integration_runtime_managed": resourceArmDataFactoryIntegrationRuntimeManaged(), + "azurerm_data_factory_integration_runtime_self_hosted": resourceArmDataFactoryIntegrationRuntimeSelfHosted(), "azurerm_data_factory_linked_service_data_lake_storage_gen2": resourceArmDataFactoryLinkedServiceDataLakeStorageGen2(), "azurerm_data_factory_linked_service_key_vault": resourceArmDataFactoryLinkedServiceKeyVault(), "azurerm_data_factory_linked_service_mysql": resourceArmDataFactoryLinkedServiceMySQL(), diff --git a/azurerm/internal/services/datafactory/tests/data_factory_integration_runtime_self_hosted_test.go b/azurerm/internal/services/datafactory/tests/data_factory_integration_runtime_self_hosted_test.go new file mode 100644 index 000000000000..ca536606c5da --- /dev/null +++ b/azurerm/internal/services/datafactory/tests/data_factory_integration_runtime_self_hosted_test.go @@ -0,0 +1,275 @@ +package tests + +import ( + "fmt" + "net/http" + "testing" + + "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/internal/services/datafactory/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMDataFactoryIntegrationRuntimeSelfHosted_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_factory_integration_runtime_self_hosted", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMDataFactoryIntegrationRuntimeSelfHostedDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMDataFactoryIntegrationRuntimeSelfHosted_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDataFactoryIntegrationRuntimeSelfHostedExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMDataFactoryIntegrationRuntimeSelfHosted_rbac(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_factory_integration_runtime_self_hosted", "target") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMDataFactoryIntegrationRuntimeSelfHostedDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMDataFactoryIntegrationRuntimeSelfHosted_rbac(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDataFactoryIntegrationRuntimeSelfHostedExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "rbac_authorization.#", "1"), + ), + }, + data.ImportStep(), + }, + }) +} + +func testAccAzureRMDataFactoryIntegrationRuntimeSelfHosted_basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-df-%d" + location = "%s" +} + +resource "azurerm_data_factory" "test" { + name = "acctestdfirsh%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_data_factory_integration_runtime_self_hosted" "test" { + name = "acctestSIR%d" + data_factory_name = azurerm_data_factory.test.name + resource_group_name = azurerm_resource_group.test.name +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMDataFactoryIntegrationRuntimeSelfHosted_rbac(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-df-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestnw-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "acctpip-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Dynamic" +} + +resource "azurerm_network_interface" "test" { + name = "acctestnic-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "internal" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.test.id + } +} + +resource "azurerm_virtual_machine" "test" { + name = "acctvm%s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + network_interface_ids = [azurerm_network_interface.test.id] + vm_size = "Standard_F4" + + storage_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "acctvm%s" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_windows_config { + timezone = "Pacific Standard Time" + provision_vm_agent = true + } +} + +resource "azurerm_virtual_machine_extension" "test" { + name = "acctestExt-%d" + virtual_machine_id = azurerm_virtual_machine.test.id + publisher = "Microsoft.Compute" + type = "CustomScriptExtension" + type_handler_version = "1.10" + settings = jsonencode({ + "fileUris" = ["https://raw.githubusercontent.com/Azure/azure-quickstart-templates/00b79d2102c88b56502a63041936ef4dd62cf725/101-vms-with-selfhost-integration-runtime/gatewayInstall.ps1"], + "commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File gatewayInstall.ps1 ${azurerm_data_factory_integration_runtime_self_hosted.host.auth_key_1} && timeout /t 120" + }) +} + +resource "azurerm_resource_group" "host" { + name = "acctesthostRG-df-%d" + location = "%s" +} + +resource "azurerm_data_factory" "host" { + name = "acctestdfirshh%d" + location = azurerm_resource_group.host.location + resource_group_name = azurerm_resource_group.host.name +} + +resource "azurerm_data_factory_integration_runtime_self_hosted" "host" { + name = "acctestirshh%d" + data_factory_name = azurerm_data_factory.host.name + resource_group_name = azurerm_resource_group.host.name +} + +resource "azurerm_resource_group" "target" { + name = "acctesttargetRG-%d" + location = "%s" +} + +resource "azurerm_role_assignment" "target" { + scope = azurerm_data_factory.host.id + role_definition_name = "Contributor" + principal_id = azurerm_data_factory.target.identity[0].principal_id +} + +resource "azurerm_data_factory" "target" { + name = "acctestdfirsht%d" + location = azurerm_resource_group.target.location + resource_group_name = azurerm_resource_group.target.name + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_data_factory_integration_runtime_self_hosted" "target" { + name = "acctestirsht%d" + data_factory_name = azurerm_data_factory.target.name + resource_group_name = azurerm_resource_group.target.name + + rbac_authorization { + resource_id = azurerm_data_factory_integration_runtime_self_hosted.host.id + } + + depends_on = [azurerm_role_assignment.target, azurerm_virtual_machine_extension.test] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomString, data.RandomInteger, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func testCheckAzureRMDataFactoryIntegrationRuntimeSelfHostedExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).DataFactory.IntegrationRuntimesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + id, err := parse.DataFactoryIntegrationRuntimeID(rs.Primary.ID) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.DataFactory, id.Name, "") + if err != nil { + return fmt.Errorf("Bad: Get on IntegrationRuntimesClient: %+v", err) + } + + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Data Factory Self-hosted Integration Runtime %q (Resource Group: %q, Data Factory %q) does not exist", id.Name, id.DataFactory, id.ResourceGroup) + } + + return nil + } +} + +func testCheckAzureRMDataFactoryIntegrationRuntimeSelfHostedDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).DataFactory.IntegrationRuntimesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_data_factory_integration_self_hosted" { + continue + } + + id, err := parse.DataFactoryIntegrationRuntimeID(rs.Primary.ID) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.DataFactory, id.Name, "") + if err != nil { + return fmt.Errorf("Bad: Get on IntegrationRuntimesClient: %+v", err) + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Data Factory Self-hosted Integration Runtime still exists:\n%#v", resp.Properties) + } + } + + return nil +} diff --git a/examples/data-factory/shared-self-hosted/README.md b/examples/data-factory/shared-self-hosted/README.md new file mode 100644 index 000000000000..da5a80f02eee --- /dev/null +++ b/examples/data-factory/shared-self-hosted/README.md @@ -0,0 +1,3 @@ +## Example: Basic Shared Self-hosted Integration Runtime + +This example provisions a Shared Self-hosted Integration Runtime, installs the Integration Runtime Agent, and a linked Self-hosted Integration Runtime. diff --git a/examples/data-factory/shared-self-hosted/main.tf b/examples/data-factory/shared-self-hosted/main.tf new file mode 100644 index 000000000000..a290c707429d --- /dev/null +++ b/examples/data-factory/shared-self-hosted/main.tf @@ -0,0 +1,255 @@ + +resource "azurerm_virtual_network" "example" { + name = "${var.prefix}-VN" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_subnet" "example" { + name = "${var.prefix}-SN" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefix = "10.0.0.0/24" +} + +resource "azurerm_subnet_network_security_group_association" "example" { + subnet_id = azurerm_subnet.example.id + network_security_group_id = azurerm_network_security_group.example.id +} + +resource "azurerm_public_ip" "vm" { + name = "${var.prefix}-PIP" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + allocation_method = "Dynamic" +} + +resource "azurerm_network_security_group" "example" { + name = "${var.prefix}-NSG" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_network_security_rule" "RDPRule" { + name = "RDPRule" + resource_group_name = azurerm_resource_group.example.name + priority = 1000 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = 3389 + source_address_prefix = "167.220.255.0/25" + destination_address_prefix = "*" + network_security_group_name = azurerm_network_security_group.example.name +} + +resource "azurerm_network_security_rule" "MSSQLRule" { + name = "MSSQLRule" + resource_group_name = azurerm_resource_group.example.name + priority = 1001 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = 1433 + source_address_prefix = "167.220.255.0/25" + destination_address_prefix = "*" + network_security_group_name = azurerm_network_security_group.example.name +} + +resource "azurerm_network_interface" "example" { + name = "${var.prefix}-NIC" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + ip_configuration { + name = "exampleconfiguration1" + subnet_id = azurerm_subnet.example.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.vm.id + } +} + +resource "azurerm_network_interface_security_group_association" "example" { + network_interface_id = azurerm_network_interface.example.id + network_security_group_id = azurerm_network_security_group.example.id +} + +resource "azurerm_virtual_machine" "example" { + name = "${var.prefix}-VM" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + network_interface_ids = [azurerm_network_interface.example.id] + vm_size = "Standard_DS14_v2" + + storage_image_reference { + publisher = "MicrosoftSQLServer" + offer = "SQL2017-WS2016" + sku = "SQLDEV" + version = "laexample" + } + + storage_os_disk { + name = "${var.prefix}-OSDisk" + caching = "ReadOnly" + create_option = "FromImage" + managed_disk_type = "Premium_LRS" + } + + os_profile { + computer_name = "winhost01" + admin_username = "exampleadmin" + admin_password = "Password1234!" + } + + os_profile_windows_config { + timezone = "Pacific Standard Time" + provision_vm_agent = true + enable_automatic_upgrades = true + } +} + +resource "azurerm_mssql_virtual_machine" "example" { + virtual_machine_id = azurerm_virtual_machine.example.id + sql_license_type = "PAYG" +} +--- +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "${var.prefix}-resources" + location = var.location +} + +resource "azurerm_virtual_network" "test" { + name = "${var.prefix}-VN" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "${var.prefix}-PIP" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Dynamic" +} + +resource "azurerm_network_interface" "test" { + name = "${var.prefix}-INT" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "internal" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.test.id + } +} + +resource "azurerm_virtual_machine" "test" { + name = "${var.prefix}-VM" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + network_interface_ids = [ azurerm_network_interface.test.id ] + vm_size = "Standard_F4" + + storage_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "${var.prefix}-VM" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_windows_config { + timezone = "Pacific Standard Time" + provision_vm_agent = true + } +} + +resource "azurerm_virtual_machine_extension" "test" { + name = "${var.prefix}-EXT" + virtual_machine_id = azurerm_virtual_machine.test.id + publisher = "Microsoft.Compute" + type = "CustomScriptExtension" + type_handler_version = "1.10" + settings = jsonencode({ + "fileUris" = ["https://raw.githubusercontent.com/Azure/azure-quickstart-templates/00b79d2102c88b56502a63041936ef4dd62cf725/101-vms-with-selfhost-integration-runtime/gatewayInstall.ps1"], + "commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File gatewayInstall.ps1 ${azurerm_data_factory_integration_runtime_self_hosted.host.auth_key_1} && timeout /t 120" + }) +} + +resource "azurerm_resource_group" "host" { + name = "${var.prefix}-resources" + location = var.location +} + +resource "azurerm_data_factory" "host" { + name = "${var.prefix}DFHOST" + location = azurerm_resource_group.host.location + resource_group_name = azurerm_resource_group.host.name +} + +resource "azurerm_data_factory_integration_runtime_self_hosted" "host" { + name = "${var.prefix}IRHOST" + data_factory_name = azurerm_data_factory.host.name + resource_group_name = azurerm_resource_group.host.name +} + +resource "azurerm_resource_group" "target" { + name = "${var.prefix}-resources" + location = var.location +} + +resource "azurerm_role_assignment" "target" { + scope = azurerm_data_factory.host.id + role_definition_name = "Contributor" + principal_id = azurerm_data_factory.target.identity[0].principal_id +} + +resource "azurerm_data_factory" "target" { + name = "${var.prefix}DFTGT" + location = azurerm_resource_group.target.location + resource_group_name = azurerm_resource_group.target.name + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_data_factory_integration_runtime_self_hosted" "target" { + name = "${var.prefix}IRTGT" + data_factory_name = azurerm_data_factory.target.name + resource_group_name = azurerm_resource_group.target.name + + rbac_authorization { + resource_id = azurerm_data_factory_integration_runtime_self_hosted.host.id + } + + depends_on = [ azurerm_role_assignment.target, azurerm_virtual_machine_extension.test ] +} diff --git a/examples/data-factory/shared-self-hosted/variables.tf b/examples/data-factory/shared-self-hosted/variables.tf new file mode 100644 index 000000000000..3579de3cb72c --- /dev/null +++ b/examples/data-factory/shared-self-hosted/variables.tf @@ -0,0 +1,7 @@ +variable "location" { + description = "The Azure location where all resources in this example should be created." +} + +variable "prefix" { + description = "The prefix used for all resources used by this NetApp Account" +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 8ddc943e808b..ad8d61fb5b78 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -1421,6 +1421,10 @@ azurerm_data_factory_integration_runtime_managed +
  • + azurerm_data_factory_integration_runtime_self_hosted +
  • +
  • azurerm_data_factory_pipeline
  • diff --git a/website/docs/r/data_factory_integration_runtime_self_hosted.html.markdown b/website/docs/r/data_factory_integration_runtime_self_hosted.html.markdown new file mode 100644 index 000000000000..9792ccbf456b --- /dev/null +++ b/website/docs/r/data_factory_integration_runtime_self_hosted.html.markdown @@ -0,0 +1,85 @@ +--- +subcategory: "Data Factory" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_data_factory_integration_runtime_self_hosted" +description: |- + Manages a Data Factory Self-hosted Integration Runtime. +--- + +# azurerm_data_factory_integration_runtime_self_hosted + +Manages a Data Factory Self-host Integration Runtime. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "eastus" +} + +resource "azurerm_data_factory" "example" { + name = "example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_data_factory_integration_runtime_self_hosted" "example" { + name = "example" + resource_group_name = "example" + data_factory_name = "example" +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `data_factory_name` - (Required) Changing this forces a new Data Factory to be created. + +* `name` - (Required) The name which should be used for this Data Factory. Changing this forces a new Data Factory to be created. + +* `resource_group_name` - (Required) The name of the Resource Group where the Data Factory should exist. Changing this forces a new Data Factory to be created. + +--- + +* `description` - (Optional) Integration runtime description. + +* `rbac_authorization` - (Optional) A `rbac_authorization` block as defined below. + +--- + +A `rbac_authorization` block supports the following: + +* `resource_id` - (Required) The resource identifier of the integration runtime to be shared. Changing this forces a new Data Factory to be created. + +-> **Please Note**: RBAC Authorization creates a [linked Self-hosted Integration Runtime targeting the Shared Self-hosted Integration Runtime in resource_id](https://docs.microsoft.com/en-us/azure/data-factory/create-shared-self-hosted-integration-runtime-powershell#share-the-self-hosted-integration-runtime-with-another-data-factory). The linked Self-hosted Integration Runtime needs Contributor access granted to the Shared Self-hosted Data Factory. See example [Shared Self-hosted](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/data-factory/shared-self-hosted). + +For more information on the configuration, please check out the [Azure documentation](https://docs.microsoft.com/en-us/rest/api/datafactory/integrationruntimes/createorupdate#linkedintegrationruntimerbacauthorization) + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Data Factory. + +* `auth_key_1` - The primary integration runtime authentication key. + +* `auth_key_2` - The secondary integration runtime authentication key. + +## 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 Data Factory. +* `read` - (Defaults to 5 minutes) Used when retrieving the Data Factory. +* `update` - (Defaults to 30 minutes) Used when updating the Data Factory. +* `delete` - (Defaults to 30 minutes) Used when deleting the Data Factory. + +## Import + +Data Factories can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_data_factory_integration_runtime_self_hosted.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.DataFactory/factories/example/integrationruntimes/example +```