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

azurerm_spring_cloud_connection, azurerm_app_service_connection: fix inaccurate storage blob resource id #18699

Merged
merged 4 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions internal/services/serviceconnector/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/hashicorp/go-azure-sdk/resource-manager/servicelinker/2022-05-01/servicelinker"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/utils"
Expand All @@ -20,6 +21,12 @@ type AuthInfoModel struct {
Certificate string `tfschema:"certificate"`
}

type StorageBlobId struct {
SubscriptionId string
ResourceGroup string
Name string
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is now unused?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Removed. Thanks!


func authInfoSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Expand Down Expand Up @@ -270,6 +277,14 @@ func flattenTargetService(input servicelinker.TargetServiceBase) string {
if value, ok := input.(servicelinker.AzureResource); ok {
if value.Id != nil {
targetServiceId = *value.Id
if parsedId, err := parse.StorageAccountDefaultBlobID(targetServiceId); err == nil {
storageAccountId := parse.StorageAccountId{
SubscriptionId: parsedId.SubscriptionId,
ResourceGroup: parsedId.ResourceGroup,
Name: parsedId.StorageAccountName,
}
targetServiceId = storageAccountId.ID()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/web/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
Expand Down Expand Up @@ -123,9 +124,17 @@ func (r AppServiceConnectorResource) Create() sdk.ResourceFunc {

serviceConnectorProperties := servicelinker.LinkerProperties{
AuthInfo: authInfo,
TargetService: servicelinker.AzureResource{
}

if _, err := parse.StorageAccountID(model.TargetResourceId); err == nil {
targetResourceId := model.TargetResourceId + "/blobServices/default"
serviceConnectorProperties.TargetService = servicelinker.AzureResource{
Id: &targetResourceId,
}
} else {
serviceConnectorProperties.TargetService = servicelinker.AzureResource{
Id: &model.TargetResourceId,
},
}
}

if model.ClientType != "" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ func TestAccServiceConnectorAppServiceCosmosdb_basic(t *testing.T) {
})
}

func TestAccServiceConnectorAppServiceStorageBlob_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_app_service_connection", "test")
r := ServiceConnectorAppServiceResource{}

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

func TestAccServiceConnectorAppServiceCosmosdb_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_app_service_connection", "test")
r := ServiceConnectorAppServiceResource{}
Expand Down Expand Up @@ -83,6 +98,53 @@ func TestAccServiceConnectorAppService_complete(t *testing.T) {
})
}

func (r ServiceConnectorAppServiceResource) storageBlob(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%[3]d"
location = "%[1]s"
}

resource "azurerm_storage_account" "test" {
name = "acctestacc%[2]s"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
account_tier = "Standard"
account_replication_type = "LRS"
}

resource "azurerm_service_plan" "test" {
location = azurerm_resource_group.test.location
name = "testserviceplan%[2]s"
resource_group_name = azurerm_resource_group.test.name
sku_name = "P1v2"
os_type = "Linux"
}

resource "azurerm_linux_web_app" "test" {
location = azurerm_resource_group.test.location
name = "testlinuxwebapp%[2]s"
resource_group_name = azurerm_resource_group.test.name
service_plan_id = azurerm_service_plan.test.id

site_config {}
}

resource "azurerm_app_service_connection" "test" {
name = "acctestserviceconnector%[3]d"
app_service_id = azurerm_linux_web_app.test.id
target_resource_id = azurerm_storage_account.test.id
authentication {
type = "systemAssignedIdentity"
}
}
`, data.Locations.Primary, data.RandomString, data.RandomInteger)
}

func (r ServiceConnectorAppServiceResource) cosmosdbBasic(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/springcloud/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/utils"
Expand Down Expand Up @@ -124,9 +125,17 @@ func (r SpringCloudConnectorResource) Create() sdk.ResourceFunc {

serviceConnectorProperties := servicelinker.LinkerProperties{
AuthInfo: authInfo,
TargetService: servicelinker.AzureResource{
}

if _, err := parse.StorageAccountID(model.TargetResourceId); err == nil {
targetResourceId := model.TargetResourceId + "/blobServices/default"
serviceConnectorProperties.TargetService = servicelinker.AzureResource{
Id: &targetResourceId,
}
} else {
serviceConnectorProperties.TargetService = servicelinker.AzureResource{
Id: &model.TargetResourceId,
},
}
}

if model.ClientType != "" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ func TestAccServiceConnectorSpringCloudCosmosdb_basic(t *testing.T) {
})
}

func TestAccServiceConnectorSpringCloudStorageBlob_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_spring_cloud_connection", "test")
r := ServiceConnectorSpringCloudResource{}

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

func TestAccServiceConnectorSpringCloudCosmosdb_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_spring_cloud_connection", "test")
r := ServiceConnectorSpringCloudResource{}
Expand Down Expand Up @@ -99,6 +114,57 @@ resource "azurerm_spring_cloud_connection" "test" {
`, template, data.RandomString, data.RandomInteger)
}

func (r ServiceConnectorSpringCloudResource) storageBlob(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%[2]d"
location = "%[1]s"
}

resource "azurerm_storage_account" "test" {
name = "acctestacc%[3]s"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
account_tier = "Standard"
account_replication_type = "LRS"
}

resource "azurerm_spring_cloud_service" "test" {
name = "testspringcloudservice-%[3]s"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
}

resource "azurerm_spring_cloud_app" "test" {
name = "testspringcloud-%[3]s"
resource_group_name = azurerm_resource_group.test.name
service_name = azurerm_spring_cloud_service.test.name

identity {
type = "SystemAssigned"
}
}

resource "azurerm_spring_cloud_java_deployment" "test" {
name = "deploy-%[3]s"
spring_cloud_app_id = azurerm_spring_cloud_app.test.id
}

resource "azurerm_spring_cloud_connection" "test" {
name = "acctestserviceconnector%[2]d"
spring_cloud_id = azurerm_spring_cloud_java_deployment.test.id
target_resource_id = azurerm_storage_account.test.id
authentication {
type = "systemAssignedIdentity"
}
}
`, data.Locations.Primary, data.RandomInteger, data.RandomString)
}

func (r ServiceConnectorSpringCloudResource) cosmosdbUpdate(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
Expand Down
75 changes: 75 additions & 0 deletions internal/services/storage/parse/storage_account_default_blob.go
Original file line number Diff line number Diff line change
@@ -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/go-azure-helpers/resourcemanager/resourceids"
)

type StorageAccountDefaultBlobId struct {
SubscriptionId string
ResourceGroup string
StorageAccountName string
BlobServiceName string
}

func NewStorageAccountDefaultBlobID(subscriptionId, resourceGroup, storageAccountName, blobServiceName string) StorageAccountDefaultBlobId {
return StorageAccountDefaultBlobId{
SubscriptionId: subscriptionId,
ResourceGroup: resourceGroup,
StorageAccountName: storageAccountName,
BlobServiceName: blobServiceName,
}
}

func (id StorageAccountDefaultBlobId) String() string {
segments := []string{
fmt.Sprintf("Blob Service Name %q", id.BlobServiceName),
fmt.Sprintf("Storage Account Name %q", id.StorageAccountName),
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Storage Account Default Blob", segmentsStr)
}

func (id StorageAccountDefaultBlobId) ID() string {
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/%s/blobServices/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.StorageAccountName, id.BlobServiceName)
}

// StorageAccountDefaultBlobID parses a StorageAccountDefaultBlob ID into an StorageAccountDefaultBlobId struct
func StorageAccountDefaultBlobID(input string) (*StorageAccountDefaultBlobId, error) {
id, err := resourceids.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := StorageAccountDefaultBlobId{
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.StorageAccountName, err = id.PopSegment("storageAccounts"); err != nil {
return nil, err
}
if resourceId.BlobServiceName, err = id.PopSegment("blobServices"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
Loading