Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resourece: azurerm_signalr_shared_private_link_resource #16187

Merged
merged 16 commits into from
Jul 29, 2022
1 change: 1 addition & 0 deletions internal/services/signalr/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource {
return map[string]*pluginsdk.Resource{
"azurerm_signalr_service": resourceArmSignalRService(),
"azurerm_signalr_service_network_acl": resourceArmSignalRServiceNetworkACL(),
"azurerm_signalr_shared_private_link_resource": resourceSignalRSharedPrivateLinkResource(),
"azurerm_web_pubsub": resourceWebPubSub(),
"azurerm_web_pubsub_hub": resourceWebPubsubHub(),
"azurerm_web_pubsub_network_acl": resourceWebpubsubNetworkACL(),
Expand Down
177 changes: 177 additions & 0 deletions internal/services/signalr/signalr_shared_private_link_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package signalr

import (
"fmt"
"time"

"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-sdk/resource-manager/signalr/2022-02-01/signalr"
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
networkValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/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 resourceSignalRSharedPrivateLinkResource() *pluginsdk.Resource {
return &pluginsdk.Resource{
Create: resourceSignalRSharedPrivateLinkCreateUpdate,
Read: resourceSignalRSharedPrivateLinkRead,
Update: resourceSignalRSharedPrivateLinkCreateUpdate,
Delete: resourceSignalrSharedPrivateLinkDelete,

Timeouts: &pluginsdk.ResourceTimeout{
Create: pluginsdk.DefaultTimeout(30 * time.Minute),
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
Update: pluginsdk.DefaultTimeout(30 * time.Minute),
Delete: pluginsdk.DefaultTimeout(30 * time.Minute),
},

Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
_, err := signalr.ParseSharedPrivateLinkResourceIDInsensitively(id)
return err
}),

Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"signalr_service_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: signalr.ValidateSignalRID,
},

"sub_resource_name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: networkValidate.PrivateLinkSubResourceName,
},

"target_resource_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: azure.ValidateResourceID,
},

"request_message": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"status": {
Type: pluginsdk.TypeString,
Computed: true,
},
},
}
}

func resourceSignalRSharedPrivateLinkCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).SignalR.SignalRClient
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

signalrID, err := signalr.ParseSignalRID(d.Get("signalr_service_id").(string))
if err != nil {
return fmt.Errorf("parsing ID of %s: %+v", signalrID, err)
}

id := signalr.NewSharedPrivateLinkResourceID(subscriptionId, signalrID.ResourceGroupName, signalrID.ResourceName, d.Get("name").(string))
if d.IsNewResource() {
existing, err := client.SharedPrivateLinkResourcesGet(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for existing %q: %+v", id, err)
}
}
if !response.WasNotFound(existing.HttpResponse) {
return tf.ImportAsExistsError("azurerm_signalr_shared_private_link_resource", id.ID())
}
}

parameters := signalr.SharedPrivateLinkResource{
Properties: &signalr.SharedPrivateLinkResourceProperties{
GroupId: d.Get("sub_resource_name").(string),
PrivateLinkResourceId: d.Get("target_resource_id").(string),
},
}

requestMessage := d.Get("request_message").(string)
if requestMessage != "" {
parameters.Properties.RequestMessage = utils.String(requestMessage)
}

if err := client.SharedPrivateLinkResourcesCreateOrUpdateThenPoll(ctx, id, parameters); err != nil {
return fmt.Errorf("creating the shared private link for signalr %s: %+v", id, err)
}

d.SetId(id.ID())
return resourceSignalRSharedPrivateLinkRead(d, meta)
}

func resourceSignalRSharedPrivateLinkRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).SignalR.SignalRClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := signalr.ParseSharedPrivateLinkResourceID(d.Id())
if err != nil {
return err
}

resp, err := client.SharedPrivateLinkResourcesGet(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
d.SetId("")
return fmt.Errorf("%s was not found", id)
}
return fmt.Errorf("retrieving shared private link %s: %+v", id, err)
}

if model := resp.Model; model != nil {
d.Set("name", model.Name)
d.Set("signalr_service_id", signalr.NewSignalRID(id.SubscriptionId, id.ResourceGroupName, id.ResourceName).ID())

if props := model.Properties; props != nil {
d.Set("sub_resource_name", props.GroupId)
d.Set("target_resource_id", props.PrivateLinkResourceId)

if props.RequestMessage != nil {
d.Set("request_message", props.RequestMessage)
}

status := string(*props.Status)
d.Set("status", status)
}
}
return nil
}

func resourceSignalrSharedPrivateLinkDelete(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).SignalR.SignalRClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := signalr.ParseSharedPrivateLinkResourceIDInsensitively(d.Id())
if err != nil {
return err
}

if err := client.SharedPrivateLinkResourcesDeleteThenPoll(ctx, *id); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package signalr_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-sdk/resource-manager/signalr/2022-02-01/signalr"
"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/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type SignalrSharedPrivateLinkResource struct{}

func TestAccSignalrSharedPrivateLinkResource_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_signalr_shared_private_link_resource", "test")
r := SignalrSharedPrivateLinkResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r)),
},
data.ImportStep(),
})
}

func TestAccSignalrSharedPrivateLinkResource_basicSites(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_signalr_shared_private_link_resource", "test")
r := SignalrSharedPrivateLinkResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basicSites(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r)),
},
data.ImportStep(),
})
}

func TestAccSignalrSharedPrivateLinkResource_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_signalr_shared_private_link_resource", "test")
r := SignalrSharedPrivateLinkResource{}

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 SignalrSharedPrivateLinkResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := signalr.ParseSharedPrivateLinkResourceIDInsensitively(state.ID)
if err != nil {
return nil, err
}
resp, err := clients.SignalR.SignalRClient.SharedPrivateLinkResourcesGet(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return utils.Bool(false), nil
}
return nil, fmt.Errorf("retrieving %s: %+v", id, err)
}
return utils.Bool(true), nil
}

func (r SignalrSharedPrivateLinkResource) basic(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
%s
resource "azurerm_key_vault" "test" {
name = "vault%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 7
access_policy {
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
certificate_permissions = [
"ManageContacts",
]
key_permissions = [
"Create",
]
secret_permissions = [
"Set",
]
}
}

resource "azurerm_signalr_shared_private_link_resource" "test" {
name = "acctest-%d"
signalr_service_id = azurerm_signalr_service.test.id
sub_resource_name = "vault"
target_resource_id = azurerm_key_vault.test.id
request_message = "please approve"
}
`, template, data.RandomInteger, data.RandomInteger)
}

func (r SignalrSharedPrivateLinkResource) requiresImport(data acceptance.TestData) string {
config := r.basic(data)
return fmt.Sprintf(`
%s

resource "azurerm_signalr_shared_private_link_resource" "import" {
name = azurerm_signalr_shared_private_link_resource.test.name
signalr_service_id = azurerm_signalr_shared_private_link_resource.test.signalr_service_id
sub_resource_name = azurerm_signalr_shared_private_link_resource.test.sub_resource_name
target_resource_id = azurerm_signalr_shared_private_link_resource.test.target_resource_id
}
`, config)
}

func (r SignalrSharedPrivateLinkResource) basicSites(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_service_plan" "test" {
name = "acctestASP-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
os_type = "Windows"
sku_name = "S1"

}
resource "azurerm_windows_web_app" "test" {
name = "acctestWA-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
service_plan_id = azurerm_service_plan.test.id

site_config {}
}

resource "azurerm_signalr_shared_private_link_resource" "test" {
name = "acctest-%d"
signalr_service_id = azurerm_signalr_service.test.id
sub_resource_name = "sites"
target_resource_id = azurerm_windows_web_app.test.id
request_message = "please approve"
}
`, r.template(data), data.RandomInteger, data.RandomInteger, data.RandomInteger)
}
func (SignalrSharedPrivateLinkResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "test" {
name = "acctestRG-signalr-%d"
location = "%s"
}

resource "azurerm_signalr_service" "test" {
name = "acctestSignalr-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name

sku {
name = "Standard_S1"
capacity = 1
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}
Loading