Skip to content

Commit

Permalink
New Resource - azurerm_role_assignment_marketplace (#22398)
Browse files Browse the repository at this point in the history
* add code

* add code

* format

* fix build

* fix test

* fix lint

* fix lint

* resolve comments

* rename `azurerm_role_assignment_marketplace` to `azurerm_marketplace_role_assignment`

* fix gen check
  • Loading branch information
ms-zhenhua authored Jul 24, 2023
1 parent fa2efb0 commit 49bf0dc
Show file tree
Hide file tree
Showing 44 changed files with 3,273 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/labeler-issue-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ service/attestation:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_attestation_provider((.|\n)*)###'

service/authorization:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(client_config|federated_identity_credential|pim_|role_|user_assigned_identity)((.|\n)*)###'
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(client_config|federated_identity_credential|marketplace_role_assignment|pim_|role_|user_assigned_identity)((.|\n)*)###'

service/automanage:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_automanage_configuration((.|\n)*)###'
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ func SupportedTypedServices() []sdk.TypedServiceRegistration {
applicationinsights.Registration{},
appservice.Registration{},
arckubernetes.Registration{},
authorization.Registration{},
automanage.Registration{},
automation.Registration{},
authorization.Registration{},
batch.Registration{},
bot.Registration{},
cognitive.Registration{},
Expand Down
18 changes: 18 additions & 0 deletions internal/services/authorization/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleassignmentschedulerequests"
"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityscheduleinstances"
"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityschedulerequests"
"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roleassignments"
"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roledefinitions"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)

Expand All @@ -21,6 +23,8 @@ type Client struct {
RoleAssignmentScheduleInstancesClient *roleassignmentscheduleinstances.RoleAssignmentScheduleInstancesClient
RoleEligibilityScheduleRequestClient *roleeligibilityschedulerequests.RoleEligibilityScheduleRequestsClient
RoleEligibilityScheduleInstancesClient *roleeligibilityscheduleinstances.RoleEligibilityScheduleInstancesClient
ScopedRoleAssignmentsClient *roleassignments.RoleAssignmentsClient
ScopedRoleDefinitionsClient *roledefinitions.RoleDefinitionsClient
}

func NewClient(o *common.ClientOptions) (*Client, error) {
Expand Down Expand Up @@ -55,12 +59,26 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
}
o.Configure(roleEligibilityScheduleInstancesClient.Client, o.Authorizers.ResourceManager)

scopedRoleAssignmentsClient, err := roleassignments.NewRoleAssignmentsClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building Role Assignment Client: %+v", err)
}
o.Configure(scopedRoleAssignmentsClient.Client, o.Authorizers.ResourceManager)

scopedRoleDefinitionsClient, err := roledefinitions.NewRoleDefinitionsClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building Role Definition Client: %+v", err)
}
o.Configure(scopedRoleDefinitionsClient.Client, o.Authorizers.ResourceManager)

return &Client{
RoleAssignmentsClient: &roleAssignmentsClient,
RoleDefinitionsClient: &roleDefinitionsClient,
RoleAssignmentScheduleRequestClient: roleAssignmentScheduleRequestsClient,
RoleAssignmentScheduleInstancesClient: roleAssignmentScheduleInstancesClient,
RoleEligibilityScheduleRequestClient: roleEligibilityScheduleRequestClient,
RoleEligibilityScheduleInstancesClient: roleEligibilityScheduleInstancesClient,
ScopedRoleAssignmentsClient: scopedRoleAssignmentsClient,
ScopedRoleDefinitionsClient: scopedRoleDefinitionsClient,
}, nil
}
60 changes: 60 additions & 0 deletions internal/services/authorization/parse/id_scopedroleassignment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package parse

import (
"fmt"
"strings"

"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roleassignments"
)

type ScopedRoleAssignmentId struct {
ScopedId roleassignments.ScopedRoleAssignmentId
TenantId string
}

func NewScopedRoleAssignmentID(scope string, roleAssignmentName string, tenantId string) ScopedRoleAssignmentId {
return ScopedRoleAssignmentId{
ScopedId: roleassignments.NewScopedRoleAssignmentID(scope, roleAssignmentName),
TenantId: tenantId,
}
}

func ScopedRoleAssignmentID(input string) (*ScopedRoleAssignmentId, error) {
azureResourceId, tenantId := DestructRoleAssignmentId(input)
scopedId, err := roleassignments.ParseScopedRoleAssignmentID(azureResourceId)
if err != nil {
return nil, err
}

return &ScopedRoleAssignmentId{ScopedId: *scopedId, TenantId: tenantId}, nil
}

func ValidateScopedRoleAssignmentID(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 := ScopedRoleAssignmentID(v); err != nil {
errors = append(errors, err)
}

return
}

func (id ScopedRoleAssignmentId) ID() string {
return ConstructRoleAssignmentId(id.ScopedId.ID(), id.TenantId)
}

func (id ScopedRoleAssignmentId) String() string {
components := []string{
id.ScopedId.String(),
}

if id.TenantId != "" {
components = append(components, fmt.Sprintf("Tenant ID: %s", id.TenantId))
}

return fmt.Sprintf("Scoped Role Assignment (%s)", strings.Join(components, "\n"))
}
124 changes: 124 additions & 0 deletions internal/services/authorization/parse/id_scopedroleassignment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package parse

import (
"testing"

"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roleassignments"
)

func TestScopedRoleAssignmentID(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *ScopedRoleAssignmentId
}{
{
Input: "",
Error: true,
},

{
Input: "/",
Error: true,
},

{
Input: "/providers/Microsoft.Marketplace/providers/Microsoft.Authorization/roleAssignments/",
Error: true,
},

{
Input: "/providers/Microsoft.Subscription/providers/Microsoft.Authorization/roleAssignments/23456781-2349-8764-5631-234567890121",
Expected: &ScopedRoleAssignmentId{
ScopedId: roleassignments.NewScopedRoleAssignmentID("/providers/Microsoft.Subscription", "23456781-2349-8764-5631-234567890121"),
},
},

{
Input: "/providers/Microsoft.Marketplace/providers/Microsoft.Authorization/roleAssignments/23456781-2349-8764-5631-234567890121",
Expected: &ScopedRoleAssignmentId{
ScopedId: roleassignments.NewScopedRoleAssignmentID("/providers/Microsoft.Marketplace", "23456781-2349-8764-5631-234567890121"),
},
},

{
Input: "/providers/Microsoft.Marketplace/providers/Microsoft.Authorization/roleAssignments/23456781-2349-8764-5631-234567890121|12345678-1234-5678-1234-567890123456",
Expected: &ScopedRoleAssignmentId{
ScopedId: roleassignments.NewScopedRoleAssignmentID("/providers/Microsoft.Marketplace", "23456781-2349-8764-5631-234567890121"),
TenantId: "12345678-1234-5678-1234-567890123456",
},
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := ScopedRoleAssignmentID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("expected a value but got an error: %+v", err)
}

if v.Error {
t.Fatal("Expect an error but didn't get one")
}

if actual.ScopedId.RoleAssignmentName != v.Expected.ScopedId.RoleAssignmentName {
t.Fatalf("Expected %q but got %q for Role Assignment Name", v.Expected.ScopedId.RoleAssignmentName, actual.ScopedId.RoleAssignmentName)
}

if actual.TenantId != v.Expected.TenantId {
t.Fatalf("Expected %q but got %q for Tenant ID", v.Expected.TenantId, actual.TenantId)
}
}
}

func TestValidateScopedRoleAssignmentID(t *testing.T) {
cases := []struct {
Input string
Valid bool
}{

{
Input: "",
Valid: false,
},

{
Input: "/",
Valid: false,
},

{
Input: "/providers/Microsoft.Marketplace/providers/Microsoft.Authorization/roleAssignments/",
Valid: false,
},

{
Input: "/providers/Microsoft.Subscription/providers/Microsoft.Authorization/roleAssignments/23456781-2349-8764-5631-234567890121",
Valid: true,
},

{
Input: "/providers/Microsoft.Marketplace/providers/Microsoft.Authorization/roleAssignments/23456781-2349-8764-5631-234567890121",
Valid: true,
},

{
Input: "/providers/Microsoft.Marketplace/providers/Microsoft.Authorization/roleAssignments/23456781-2349-8764-5631-234567890121|12345678-1234-5678-1234-567890123456",
Valid: true,
},
}
for _, tc := range cases {
t.Logf("[DEBUG] Testing Value %s", tc.Input)
_, errors := ValidateScopedRoleAssignmentID(tc.Input, "test")
valid := len(errors) == 0

if tc.Valid != valid {
t.Fatalf("Expected %t but got %t", tc.Valid, valid)
}
}
}
8 changes: 8 additions & 0 deletions internal/services/authorization/parse/role_assignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ func ConstructRoleAssignmentId(azureResourceId, tenantId string) string {
return fmt.Sprintf("%s|%s", azureResourceId, tenantId)
}

func DestructRoleAssignmentId(id string) (string, string) {
parts := strings.Split(id, "|")
if len(parts) == 2 {
return parts[0], parts[1]
}
return id, ""
}

func RoleAssignmentID(input string) (*RoleAssignmentId, error) {
if len(input) == 0 {
return nil, fmt.Errorf("Role Assignment ID is empty string")
Expand Down
1 change: 1 addition & 0 deletions internal/services/authorization/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (r Registration) Resources() []sdk.Resource {
resources := []sdk.Resource{
PimActiveRoleAssignmentResource{},
PimEligibleRoleAssignmentResource{},
RoleAssignmentMarketplaceResource{},
}
return resources
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package authorization

import (
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/authorization/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

const (
MarketplaceScope = "/providers/Microsoft.Marketplace"
)

var _ sdk.Resource = RoleAssignmentMarketplaceResource{}

type RoleAssignmentMarketplaceResource struct {
base roleAssignmentBaseResource
}

func (r RoleAssignmentMarketplaceResource) Arguments() map[string]*pluginsdk.Schema {
return r.base.arguments()
}

func (r RoleAssignmentMarketplaceResource) Attributes() map[string]*pluginsdk.Schema {
return r.base.attributes()
}

func (r RoleAssignmentMarketplaceResource) Create() sdk.ResourceFunc {
return r.base.createFunc(r.ResourceType(), MarketplaceScope)
}

func (r RoleAssignmentMarketplaceResource) Delete() sdk.ResourceFunc {
return r.base.deleteFunc()
}

func (r RoleAssignmentMarketplaceResource) Read() sdk.ResourceFunc {
return r.base.readFunc(MarketplaceScope, true)
}

func (r RoleAssignmentMarketplaceResource) ResourceType() string {
return "azurerm_marketplace_role_assignment"
}

func (r RoleAssignmentMarketplaceResource) ModelObject() interface{} {
return nil
}

func (r RoleAssignmentMarketplaceResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return parse.ValidateScopedRoleAssignmentID
}
Loading

0 comments on commit 49bf0dc

Please sign in to comment.