diff --git a/internal/services/datafactory/data_factory_integration_runtime_self_hosted_resource.go b/internal/services/datafactory/data_factory_integration_runtime_self_hosted_resource.go index be314018bd91..820bba64dc23 100644 --- a/internal/services/datafactory/data_factory_integration_runtime_self_hosted_resource.go +++ b/internal/services/datafactory/data_factory_integration_runtime_self_hosted_resource.go @@ -77,11 +77,13 @@ func resourceDataFactoryIntegrationRuntimeSelfHosted() *pluginsdk.Resource { }, }, + // todo: rename to authorization_key_primary in v3.0 "auth_key_1": { Type: pluginsdk.TypeString, Computed: true, }, + // todo: rename to authorization_key_secondary in v3.0 "auth_key_2": { Type: pluginsdk.TypeString, Computed: true, diff --git a/internal/services/synapse/client/client.go b/internal/services/synapse/client/client.go index 01fbde45fd99..92aa62f45e5e 100644 --- a/internal/services/synapse/client/client.go +++ b/internal/services/synapse/client/client.go @@ -12,6 +12,8 @@ import ( type Client struct { FirewallRulesClient *synapse.IPFirewallRulesClient + IntegrationRuntimesClient *synapse.IntegrationRuntimesClient + IntegrationRuntimeAuthKeysClient *synapse.IntegrationRuntimeAuthKeysClient PrivateLinkHubsClient *synapse.PrivateLinkHubsClient SparkPoolClient *synapse.BigDataPoolsClient SqlPoolClient *synapse.SQLPoolsClient @@ -27,6 +29,12 @@ func NewClient(o *common.ClientOptions) *Client { firewallRuleClient := synapse.NewIPFirewallRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&firewallRuleClient.Client, o.ResourceManagerAuthorizer) + integrationRuntimesClient := synapse.NewIntegrationRuntimesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&integrationRuntimesClient.Client, o.ResourceManagerAuthorizer) + + integrationRuntimeAuthKeysClient := synapse.NewIntegrationRuntimeAuthKeysClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&integrationRuntimeAuthKeysClient.Client, o.ResourceManagerAuthorizer) + privateLinkHubsClient := synapse.NewPrivateLinkHubsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&privateLinkHubsClient.Client, o.ResourceManagerAuthorizer) @@ -51,6 +59,8 @@ func NewClient(o *common.ClientOptions) *Client { return &Client{ FirewallRulesClient: &firewallRuleClient, + IntegrationRuntimesClient: &integrationRuntimesClient, + IntegrationRuntimeAuthKeysClient: &integrationRuntimeAuthKeysClient, PrivateLinkHubsClient: &privateLinkHubsClient, SparkPoolClient: &sparkPoolClient, SqlPoolClient: &sqlPoolClient, diff --git a/internal/services/synapse/parse/integration_runtime.go b/internal/services/synapse/parse/integration_runtime.go new file mode 100644 index 000000000000..a8c64548073a --- /dev/null +++ b/internal/services/synapse/parse/integration_runtime.go @@ -0,0 +1,75 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + "strings" + + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" +) + +type IntegrationRuntimeId struct { + SubscriptionId string + ResourceGroup string + WorkspaceName string + Name string +} + +func NewIntegrationRuntimeID(subscriptionId, resourceGroup, workspaceName, name string) IntegrationRuntimeId { + return IntegrationRuntimeId{ + SubscriptionId: subscriptionId, + ResourceGroup: resourceGroup, + WorkspaceName: workspaceName, + Name: name, + } +} + +func (id IntegrationRuntimeId) String() string { + segments := []string{ + fmt.Sprintf("Name %q", id.Name), + fmt.Sprintf("Workspace Name %q", id.WorkspaceName), + fmt.Sprintf("Resource Group %q", id.ResourceGroup), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "Integration Runtime", segmentsStr) +} + +func (id IntegrationRuntimeId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Synapse/workspaces/%s/integrationruntimes/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.WorkspaceName, id.Name) +} + +// IntegrationRuntimeID parses a IntegrationRuntime ID into an IntegrationRuntimeId struct +func IntegrationRuntimeID(input string) (*IntegrationRuntimeId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := IntegrationRuntimeId{ + 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.WorkspaceName, err = id.PopSegment("workspaces"); err != nil { + return nil, err + } + if resourceId.Name, err = id.PopSegment("integrationruntimes"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/internal/services/synapse/parse/integration_runtime_test.go b/internal/services/synapse/parse/integration_runtime_test.go new file mode 100644 index 000000000000..2f725e535225 --- /dev/null +++ b/internal/services/synapse/parse/integration_runtime_test.go @@ -0,0 +1,128 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/resourceid" +) + +var _ resourceid.Formatter = IntegrationRuntimeId{} + +func TestIntegrationRuntimeIDFormatter(t *testing.T) { + actual := NewIntegrationRuntimeID("12345678-1234-9876-4563-123456789012", "resGroup1", "workspace1", "IntegrationRuntime1").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/integrationruntimes/IntegrationRuntime1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestIntegrationRuntimeID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *IntegrationRuntimeId + }{ + + { + // 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 WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/", + Error: true, + }, + + { + // missing value for WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/", + Error: true, + }, + + { + // missing Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/", + Error: true, + }, + + { + // missing value for Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/integrationruntimes/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/integrationruntimes/IntegrationRuntime1", + Expected: &IntegrationRuntimeId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroup: "resGroup1", + WorkspaceName: "workspace1", + Name: "IntegrationRuntime1", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.SYNAPSE/WORKSPACES/WORKSPACE1/INTEGRATIONRUNTIMES/INTEGRATIONRUNTIME1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := IntegrationRuntimeID(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.WorkspaceName != v.Expected.WorkspaceName { + t.Fatalf("Expected %q but got %q for WorkspaceName", v.Expected.WorkspaceName, actual.WorkspaceName) + } + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + } +} diff --git a/internal/services/synapse/registration.go b/internal/services/synapse/registration.go index fa68b8a8e66c..75a35c476c5f 100644 --- a/internal/services/synapse/registration.go +++ b/internal/services/synapse/registration.go @@ -26,12 +26,13 @@ func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{ - "azurerm_synapse_firewall_rule": resourceSynapseFirewallRule(), - "azurerm_synapse_private_link_hub": resourceSynapsePrivateLinkHub(), - "azurerm_synapse_managed_private_endpoint": resourceSynapseManagedPrivateEndpoint(), - "azurerm_synapse_role_assignment": resourceSynapseRoleAssignment(), - "azurerm_synapse_spark_pool": resourceSynapseSparkPool(), - "azurerm_synapse_sql_pool": resourceSynapseSqlPool(), - "azurerm_synapse_workspace": resourceSynapseWorkspace(), + "azurerm_synapse_firewall_rule": resourceSynapseFirewallRule(), + "azurerm_synapse_integration_runtime_self_hosted": resourceSynapseIntegrationRuntimeSelfHosted(), + "azurerm_synapse_private_link_hub": resourceSynapsePrivateLinkHub(), + "azurerm_synapse_managed_private_endpoint": resourceSynapseManagedPrivateEndpoint(), + "azurerm_synapse_role_assignment": resourceSynapseRoleAssignment(), + "azurerm_synapse_spark_pool": resourceSynapseSparkPool(), + "azurerm_synapse_sql_pool": resourceSynapseSqlPool(), + "azurerm_synapse_workspace": resourceSynapseWorkspace(), } } diff --git a/internal/services/synapse/resourceids.go b/internal/services/synapse/resourceids.go index 19a9765b2362..380adaeb678e 100644 --- a/internal/services/synapse/resourceids.go +++ b/internal/services/synapse/resourceids.go @@ -7,3 +7,4 @@ package synapse //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Workspace -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ManagedPrivateEndpoint -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/managedVirtualNetworks/default/managedPrivateEndpoints/endpoint1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=PrivateLinkHub -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/privateLinkHubs/privateLinkHub1 +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=IntegrationRuntime -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/integrationruntimes/IntegrationRuntime1 diff --git a/internal/services/synapse/synapse_integration_runtime_self_hosted_resource.go b/internal/services/synapse/synapse_integration_runtime_self_hosted_resource.go new file mode 100644 index 000000000000..84adfae259a6 --- /dev/null +++ b/internal/services/synapse/synapse_integration_runtime_self_hosted_resource.go @@ -0,0 +1,187 @@ +package synapse + +import ( + "fmt" + "regexp" + "time" + + "github.com/Azure/azure-sdk-for-go/services/synapse/mgmt/2021-03-01/synapse" + "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/synapse/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/synapse/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func resourceSynapseIntegrationRuntimeSelfHosted() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceSynapseIntegrationRuntimeSelfHostedCreateUpdate, + Read: resourceSynapseIntegrationRuntimeSelfHostedRead, + Update: resourceSynapseIntegrationRuntimeSelfHostedCreateUpdate, + Delete: resourceSynapseIntegrationRuntimeSelfHostedDelete, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.IntegrationRuntimeID(id) + return err + }), + + 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), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.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.`, + ), + }, + + "synapse_workspace_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.WorkspaceID, + }, + + "description": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "authorization_key_primary": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "authorization_key_secondary": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + } +} + +func resourceSynapseIntegrationRuntimeSelfHostedCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Synapse.IntegrationRuntimesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + workspaceId, err := parse.WorkspaceID(d.Get("synapse_workspace_id").(string)) + if err != nil { + return err + } + + id := parse.NewIntegrationRuntimeID(workspaceId.SubscriptionId, workspaceId.ResourceGroup, workspaceId.Name, d.Get("name").(string)) + if d.IsNewResource() { + existing, err := client.Get(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, "") + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) + } + } + if !utils.ResponseWasNotFound(existing.Response) { + return tf.ImportAsExistsError("azurerm_synapse_integration_runtime_self_hosted", *existing.ID) + } + } + + integrationRuntime := synapse.IntegrationRuntimeResource{ + Name: utils.String(id.Name), + Properties: synapse.SelfHostedIntegrationRuntime{ + Description: utils.String(d.Get("description").(string)), + Type: synapse.TypeSelfHosted, + }, + } + + future, err := client.Create(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, integrationRuntime, "") + 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 on creation for %s: %+v", id, err) + } + + d.SetId(id.ID()) + + return resourceSynapseIntegrationRuntimeSelfHostedRead(d, meta) +} + +func resourceSynapseIntegrationRuntimeSelfHostedRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Synapse.IntegrationRuntimesClient + authKeysClient := meta.(*clients.Client).Synapse.IntegrationRuntimeAuthKeysClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.IntegrationRuntimeID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + d.Set("name", id.Name) + d.Set("synapse_workspace_id", parse.NewWorkspaceID(id.SubscriptionId, id.ResourceGroup, id.WorkspaceName).ID()) + + selfHostedIntegrationRuntime, convertSuccess := resp.Properties.AsSelfHostedIntegrationRuntime() + + if !convertSuccess { + return fmt.Errorf("converting integration runtime to Self-Hosted integration runtime (%q)", id) + } + + d.Set("description", selfHostedIntegrationRuntime.Description) + + respKey, err := authKeysClient.List(ctx, id.ResourceGroup, id.WorkspaceName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(respKey.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving auth keys (%q): %+v", id, err) + } + + d.Set("authorization_key_primary", respKey.AuthKey1) + d.Set("authorization_key_secondary", respKey.AuthKey2) + + return nil +} + +func resourceSynapseIntegrationRuntimeSelfHostedDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Synapse.IntegrationRuntimesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.IntegrationRuntimeID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ResourceGroup, id.WorkspaceName, id.Name) + 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 %s to be deleted: %+v", id, err) + } + + return nil +} diff --git a/internal/services/synapse/synapse_integration_runtime_self_hosted_resource_test.go b/internal/services/synapse/synapse_integration_runtime_self_hosted_resource_test.go new file mode 100644 index 000000000000..28bdd58fd2ff --- /dev/null +++ b/internal/services/synapse/synapse_integration_runtime_self_hosted_resource_test.go @@ -0,0 +1,131 @@ +package synapse_test + +import ( + "context" + "fmt" + "testing" + + "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/synapse/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type IntegrationRuntimeSelfHostedResource struct { +} + +func TestAccSynapseIntegrationRuntimeSelfHosted_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_synapse_integration_runtime_self_hosted", "test") + r := IntegrationRuntimeSelfHostedResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccSynapseIntegrationRuntimeSelfHosted_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_synapse_integration_runtime_self_hosted", "test") + r := IntegrationRuntimeSelfHostedResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func (r IntegrationRuntimeSelfHostedResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.IntegrationRuntimeID(state.ID) + if err != nil { + return nil, err + } + resp, err := clients.Synapse.IntegrationRuntimesClient.Get(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, "") + if err != nil { + return nil, fmt.Errorf("reading %s: %+v", id, err) + } + return utils.Bool(resp.ID != nil), nil +} + +func (r IntegrationRuntimeSelfHostedResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-synapse-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_storage_container" "test" { + name = "content" + storage_account_name = azurerm_storage_account.test.name + container_access_type = "private" +} + +resource "azurerm_storage_data_lake_gen2_filesystem" "test" { + name = "acctest-%d" + storage_account_id = azurerm_storage_account.test.id +} + +resource "azurerm_synapse_workspace" "test" { + name = "acctestdf%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + storage_data_lake_gen2_filesystem_id = azurerm_storage_data_lake_gen2_filesystem.test.id + sql_administrator_login = "sqladminuser" + sql_administrator_login_password = "H@Sh1CoR3!" + managed_virtual_network_enabled = true +} + +resource "azurerm_synapse_firewall_rule" "test" { + name = "AllowAll" + synapse_workspace_id = azurerm_synapse_workspace.test.id + start_ip_address = "0.0.0.0" + end_ip_address = "255.255.255.255" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func (r IntegrationRuntimeSelfHostedResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_synapse_integration_runtime_self_hosted" "test" { + name = "acctestSIR%d" + synapse_workspace_id = azurerm_synapse_workspace.test.id + description = "test" +} +`, r.template(data), data.RandomInteger) +} + +func (r IntegrationRuntimeSelfHostedResource) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_synapse_integration_runtime_self_hosted" "import" { + name = azurerm_synapse_integration_runtime_self_hosted.test.name + synapse_workspace_id = azurerm_synapse_integration_runtime_self_hosted.test.synapse_workspace_id +} +`, r.basic(data)) +} diff --git a/internal/services/synapse/validate/integration_runtime_id.go b/internal/services/synapse/validate/integration_runtime_id.go new file mode 100644 index 000000000000..62c63aec19ae --- /dev/null +++ b/internal/services/synapse/validate/integration_runtime_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/synapse/parse" +) + +func IntegrationRuntimeID(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.IntegrationRuntimeID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/internal/services/synapse/validate/integration_runtime_id_test.go b/internal/services/synapse/validate/integration_runtime_id_test.go new file mode 100644 index 000000000000..fff04caaf38e --- /dev/null +++ b/internal/services/synapse/validate/integration_runtime_id_test.go @@ -0,0 +1,88 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestIntegrationRuntimeID(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 WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/", + Valid: false, + }, + + { + // missing value for WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/", + Valid: false, + }, + + { + // missing Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/", + Valid: false, + }, + + { + // missing value for Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/integrationruntimes/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/integrationruntimes/IntegrationRuntime1", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.SYNAPSE/WORKSPACES/WORKSPACE1/INTEGRATIONRUNTIMES/INTEGRATIONRUNTIME1", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := IntegrationRuntimeID(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/synapse_integration_runtime_self_hosted.html.markdown b/website/docs/r/synapse_integration_runtime_self_hosted.html.markdown new file mode 100644 index 000000000000..a76f64712d55 --- /dev/null +++ b/website/docs/r/synapse_integration_runtime_self_hosted.html.markdown @@ -0,0 +1,101 @@ +--- +subcategory: "Synapse" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_synapse_integration_runtime_self_hosted" +description: |- + Manages a Synapse Self-hosted Integration Runtime. +--- + +# azurerm_synapse_integration_runtime_self_hosted + +Manages a Synapse Self-hosted Integration Runtime. + +## Example Usage + +```hcl + +resource "azurerm_resource_group" "example" { + name = "example" + location = "West Europe" +} + +resource "azurerm_storage_account" "example" { + name = "example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_storage_container" "example" { + name = "content" + storage_account_name = azurerm_storage_account.example.name + container_access_type = "private" +} + +resource "azurerm_storage_data_lake_gen2_filesystem" "example" { + name = "example" + storage_account_id = azurerm_storage_account.example.id +} + +resource "azurerm_synapse_workspace" "example" { + name = "example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + storage_data_lake_gen2_filesystem_id = azurerm_storage_data_lake_gen2_filesystem.example.id + sql_administrator_login = "sqladminuser" + sql_administrator_login_password = "H@Sh1CoR3!" + managed_virtual_network_enabled = true +} + +resource "azurerm_synapse_firewall_rule" "example" { + name = "AllowAll" + synapse_workspace_id = azurerm_synapse_workspace.example.id + start_ip_address = "0.0.0.0" + end_ip_address = "255.255.255.255" +} + +resource "azurerm_synapse_integration_runtime_self_hosted" "example" { + name = "example" + synapse_workspace_id = azurerm_synapse_workspace.example.id +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name which should be used for this Synapse Self-hosted Integration Runtime. Changing this forces a new Synapse Self-hosted Integration Runtime to be created. + +* `synapse_workspace_id` - (Required) The Synapse Workspace ID in which to associate the Integration Runtime with. Changing this forces a new Synapse Self-hosted Integration Runtime to be created. + +--- + +* `description` - (Optional) Integration runtime description. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Synapse Self-hosted Integration Runtime. + +* `authorization_key_primary` - The primary integration runtime authentication key. + +* `authorization_key_secondary` - 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 Synapse Self-hosted Integration Runtime. +* `read` - (Defaults to 5 minutes) Used when retrieving the Synapse Self-hosted Integration Runtime. +* `update` - (Defaults to 30 minutes) Used when updating the Synapse Self-hosted Integration Runtime. +* `delete` - (Defaults to 30 minutes) Used when deleting the Synapse Self-hosted Integration Runtime. + +## Import + +Synapse Self-hosted Integration Runtimes can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_synapse_integration_runtime_self_hosted.example /subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/integrationruntimes/IntegrationRuntime1 +```