diff --git a/internal/services/authorization/azuresdkhacks/definitions.go b/internal/services/authorization/azuresdkhacks/definitions.go index 59a7e7903765..b410c1826ec0 100644 --- a/internal/services/authorization/azuresdkhacks/definitions.go +++ b/internal/services/authorization/azuresdkhacks/definitions.go @@ -7,151 +7,119 @@ import ( "context" "net/http" - "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2020-04-01-preview/authorization" // nolint: staticcheck - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/odata" ) type RoleDefinitionsWorkaroundClient struct { - sdkClient *authorization.RoleDefinitionsClient + client *resourcemanager.Client } -func NewRoleDefinitionsWorkaroundClient(client *authorization.RoleDefinitionsClient) RoleDefinitionsWorkaroundClient { +func NewRoleDefinitionsWorkaroundClient(resourcemanagerClient *resourcemanager.Client) RoleDefinitionsWorkaroundClient { return RoleDefinitionsWorkaroundClient{ - sdkClient: client, + client: resourcemanagerClient, } } -// CreateOrUpdate creates or updates a role definition. -// Parameters: -// scope - the scope of the role definition. -// roleDefinitionID - the ID of the role definition. -// roleDefinition - the values for the role definition. -func (client RoleDefinitionsWorkaroundClient) CreateOrUpdate(ctx context.Context, scope string, roleDefinitionID string, roleDefinition authorization.RoleDefinition) (result RoleDefinitionUpdateResponse, err error) { - req, err := client.sdkClient.CreateOrUpdatePreparer(ctx, scope, roleDefinitionID, roleDefinition) +// CreateOrUpdate ... +func (c RoleDefinitionsWorkaroundClient) CreateOrUpdate(ctx context.Context, id roledefinitions.ScopedRoleDefinitionId, input RoleDefinition) (result CreateOrUpdateOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusCreated, + }, + HttpMethod: http.MethodPut, + Path: id.ID(), + } + + req, err := c.client.NewRequest(ctx, opts) if err != nil { - err = autorest.NewErrorWithError(err, "authorization.RoleDefinitionsClient", "CreateOrUpdate", nil, "Failure preparing request") return } - resp, err := client.sdkClient.CreateOrUpdateSender(req) - if err != nil { - result.Response = autorest.Response{Response: resp} - err = autorest.NewErrorWithError(err, "authorization.RoleDefinitionsClient", "CreateOrUpdate", resp, "Failure sending request") + if err = req.Marshal(input); err != nil { return } - result, err = client.CreateOrUpdateResponder(resp) + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } if err != nil { - err = autorest.NewErrorWithError(err, "authorization.RoleDefinitionsClient", "CreateOrUpdate", resp, "Failure responding to request") + return } - return -} + if err = resp.Unmarshal(&result.Model); err != nil { + return + } -// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always -// closes the http.Response Body. -func (client RoleDefinitionsWorkaroundClient) CreateOrUpdateResponder(resp *http.Response) (result RoleDefinitionUpdateResponse, err error) { - err = autorest.Respond( - resp, - azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated), - autorest.ByUnmarshallingJSON(&result), - autorest.ByClosing()) - result.Response = autorest.Response{Response: resp} return } -// Get get role definition by name (GUID). -// Parameters: -// scope - the scope of the role definition. -// roleDefinitionID - the ID of the role definition. -func (client RoleDefinitionsWorkaroundClient) Get(ctx context.Context, scope string, roleDefinitionID string) (result RoleDefinitionGetResponse, err error) { - req, err := client.sdkClient.GetPreparer(ctx, scope, roleDefinitionID) +func (c RoleDefinitionsWorkaroundClient) Get(ctx context.Context, id roledefinitions.ScopedRoleDefinitionId) (result GetOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: id.ID(), + } + + req, err := c.client.NewRequest(ctx, opts) if err != nil { - err = autorest.NewErrorWithError(err, "authorization.RoleDefinitionsClient", "Get", nil, "Failure preparing request") return } - resp, err := client.sdkClient.GetSender(req) + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } if err != nil { - result.Response = autorest.Response{Response: resp} - err = autorest.NewErrorWithError(err, "authorization.RoleDefinitionsClient", "Get", resp, "Failure sending request") return } - result, err = client.GetResponder(resp) - if err != nil { - err = autorest.NewErrorWithError(err, "authorization.RoleDefinitionsClient", "Get", resp, "Failure responding to request") + if err = resp.Unmarshal(&result.Model); err != nil { + return } return } -// GetResponder handles the response to the Get request. The method always -// closes the http.Response Body. -func (client RoleDefinitionsWorkaroundClient) GetResponder(resp *http.Response) (result RoleDefinitionGetResponse, err error) { - err = autorest.Respond( - resp, - azure.WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByUnmarshallingJSON(&result), - autorest.ByClosing()) - result.Response = autorest.Response{Response: resp} - return +type CreateOrUpdateOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleDefinition } -// RoleDefinition role definition. -type RoleDefinitionGetResponse struct { - autorest.Response `json:"-"` - // ID - READ-ONLY; The role definition ID. - ID *string `json:"id,omitempty"` - // Name - READ-ONLY; The role definition name. - Name *string `json:"name,omitempty"` - // Type - READ-ONLY; The role definition type. - Type *string `json:"type,omitempty"` - // RoleDefinitionProperties - Role definition properties. - *RoleDefinitionProperties `json:"properties,omitempty"` +type GetOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleDefinition } -type RoleDefinitionUpdateResponse struct { - autorest.Response `json:"-"` - // ID - READ-ONLY; The role definition ID. - ID *string `json:"id,omitempty"` - // Name - READ-ONLY; The role definition name. - Name *string `json:"name,omitempty"` - // Type - READ-ONLY; The role definition type. - Type *string `json:"type,omitempty"` - // RoleDefinitionProperties - Role definition properties. - *RoleDefinitionProperties `json:"properties,omitempty"` +type RoleDefinition struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *RoleDefinitionProperties `json:"properties,omitempty"` + Type *string `json:"type,omitempty"` } -// RoleDefinitionProperties role definition properties. type RoleDefinitionProperties struct { - // RoleName - The role name. - RoleName *string `json:"roleName,omitempty"` - // Description - The role definition description. - Description *string `json:"description,omitempty"` - // RoleType - The role type. - RoleType *string `json:"type,omitempty"` - // Permissions - Role definition permissions. - Permissions *[]Permission `json:"permissions,omitempty"` - // AssignableScopes - Role definition assignable scopes. - AssignableScopes *[]string `json:"assignableScopes,omitempty"` - + AssignableScopes *[]string `json:"assignableScopes,omitempty"` + Description *string `json:"description,omitempty"` + Permissions *[]roledefinitions.Permission `json:"permissions,omitempty"` + RoleName *string `json:"roleName,omitempty"` + Type *string `json:"type,omitempty"` // not exposed in the sdk CreatedOn *string `json:"createdOn,omitempty"` UpdatedOn *string `json:"updatedOn,omitempty"` CreatedBy *string `json:"createdBy,omitempty"` UpdatedBy *string `json:"updatedBy,omitempty"` } - -// Permission role definition permissions. -type Permission struct { - // Actions - Allowed actions. - Actions *[]string `json:"actions,omitempty"` - // NotActions - Denied actions. - NotActions *[]string `json:"notActions,omitempty"` - // DataActions - Allowed Data actions. - DataActions *[]string `json:"dataActions,omitempty"` - // NotDataActions - Denied Data actions. - NotDataActions *[]string `json:"notDataActions,omitempty"` -} diff --git a/internal/services/authorization/client/client.go b/internal/services/authorization/client/client.go index 457bab92b906..f3dedec0651b 100644 --- a/internal/services/authorization/client/client.go +++ b/internal/services/authorization/client/client.go @@ -7,6 +7,8 @@ import ( "fmt" "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2020-04-01-preview/authorization" // nolint: staticcheck // nolint: staticcheck + // To swap sdk for `azurerm_role_definition` without changing API version + oldRoleDefinitions "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions" "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleassignmentscheduleinstances" "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" @@ -18,7 +20,7 @@ import ( type Client struct { RoleAssignmentsClient *authorization.RoleAssignmentsClient - RoleDefinitionsClient *authorization.RoleDefinitionsClient + RoleDefinitionsClient *oldRoleDefinitions.RoleDefinitionsClient RoleAssignmentScheduleRequestClient *roleassignmentschedulerequests.RoleAssignmentScheduleRequestsClient RoleAssignmentScheduleInstancesClient *roleassignmentscheduleinstances.RoleAssignmentScheduleInstancesClient RoleEligibilityScheduleRequestClient *roleeligibilityschedulerequests.RoleEligibilityScheduleRequestsClient @@ -31,8 +33,11 @@ func NewClient(o *common.ClientOptions) (*Client, error) { roleAssignmentsClient := authorization.NewRoleAssignmentsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&roleAssignmentsClient.Client, o.ResourceManagerAuthorizer) - roleDefinitionsClient := authorization.NewRoleDefinitionsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&roleDefinitionsClient.Client, o.ResourceManagerAuthorizer) + roleDefinitionsClient, err := oldRoleDefinitions.NewRoleDefinitionsClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("creating roleDefinitionsClient: %+v", err) + } + o.Configure(roleDefinitionsClient.Client, o.Authorizers.ResourceManager) roleAssignmentScheduleRequestsClient, err := roleassignmentschedulerequests.NewRoleAssignmentScheduleRequestsClientWithBaseURI(o.Environment.ResourceManager) if err != nil { @@ -73,7 +78,7 @@ func NewClient(o *common.ClientOptions) (*Client, error) { return &Client{ RoleAssignmentsClient: &roleAssignmentsClient, - RoleDefinitionsClient: &roleDefinitionsClient, + RoleDefinitionsClient: roleDefinitionsClient, RoleAssignmentScheduleRequestClient: roleAssignmentScheduleRequestsClient, RoleAssignmentScheduleInstancesClient: roleAssignmentScheduleInstancesClient, RoleEligibilityScheduleRequestClient: roleEligibilityScheduleRequestClient, diff --git a/internal/services/authorization/role_assignment_resource.go b/internal/services/authorization/role_assignment_resource.go index 8815246ae60a..60a2d3aec3f0 100644 --- a/internal/services/authorization/role_assignment_resource.go +++ b/internal/services/authorization/role_assignment_resource.go @@ -14,6 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2020-04-01-preview/authorization" // nolint: staticcheck "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions" "github.com/hashicorp/go-azure-sdk/resource-manager/resources/2022-12-01/subscriptions" "github.com/hashicorp/go-uuid" "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" @@ -163,20 +164,26 @@ func resourceArmRoleAssignmentCreate(d *pluginsdk.ResourceData, meta interface{} name := d.Get("name").(string) scope := d.Get("scope").(string) + scopeId, err := commonids.ParseScopeID(scope) + if err != nil { + return fmt.Errorf("parsing %s: %+v", scopeId, err) + } var roleDefinitionId string if v, ok := d.GetOk("role_definition_id"); ok { roleDefinitionId = v.(string) } else if v, ok := d.GetOk("role_definition_name"); ok { roleName := v.(string) - roleDefinitions, err := roleDefinitionsClient.List(ctx, scope, fmt.Sprintf("roleName eq '%s'", roleName)) + roleDefinitions, err := roleDefinitionsClient.List(ctx, *scopeId, roledefinitions.ListOperationOptions{ + Filter: pointer.To(fmt.Sprintf("roleName eq '%s'", roleName)), + }) if err != nil { return fmt.Errorf("loading Role Definition List: %+v", err) } - if len(roleDefinitions.Values()) != 1 { + if roleDefinitions.Model == nil || len(*roleDefinitions.Model) != 1 { return fmt.Errorf("loading Role Definition List: could not find role '%s'", roleName) } - roleDefinitionId = *roleDefinitions.Values()[0].ID + roleDefinitionId = *(*roleDefinitions.Model)[0].Id } else { return fmt.Errorf("Error: either role_definition_id or role_definition_name needs to be set") } @@ -296,15 +303,25 @@ func resourceArmRoleAssignmentRead(d *pluginsdk.ResourceData, meta interface{}) d.Set("condition_version", props.ConditionVersion) // allows for import when role name is used (also if the role name changes a plan will show a diff) - if roleId := props.RoleDefinitionID; roleId != nil { - roleResp, err := roleDefinitionsClient.GetByID(ctx, *roleId) + if roleDefResourceId := props.RoleDefinitionID; roleDefResourceId != nil { + // Workaround for https://github.com/hashicorp/pandora/issues/3257 + // The role definition id returned does not contain scope when the role definition was on tenant level (management group or tenant). + // And adding tenant id as scope will cause 404 response, so just adding a slash to parse that. + if strings.HasPrefix(*roleDefResourceId, "/providers") { + roleDefResourceId = pointer.To(fmt.Sprintf("/%s", *roleDefResourceId)) + } + parsedRoleDefId, err := roledefinitions.ParseScopedRoleDefinitionID(*roleDefResourceId) if err != nil { - return fmt.Errorf("loading Role Definition %q: %+v", *roleId, err) + return fmt.Errorf("parsing %q: %+v", *roleDefResourceId, err) } - - if roleProps := roleResp.RoleDefinitionProperties; roleProps != nil { - d.Set("role_definition_name", roleProps.RoleName) + roleResp, err := roleDefinitionsClient.Get(ctx, *parsedRoleDefId) + if err != nil { + return fmt.Errorf("loading Role Definition %q: %+v", *roleDefResourceId, err) + } + if roleResp.Model != nil && roleResp.Model.Properties != nil { + d.Set("role_definition_name", pointer.From(roleResp.Model.Properties.RoleName)) } + } } diff --git a/internal/services/authorization/role_definition_data_source.go b/internal/services/authorization/role_definition_data_source.go index 9c2421635157..f723d65792f1 100644 --- a/internal/services/authorization/role_definition_data_source.go +++ b/internal/services/authorization/role_definition_data_source.go @@ -8,9 +8,9 @@ import ( "fmt" "time" - "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2020-04-01-preview/authorization" // nolint: staticcheck "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" @@ -155,7 +155,8 @@ func (a RoleDefinitionDataSource) Read() sdk.ResourceFunc { defId := config.RoleDefinitionId // search by name - var role authorization.RoleDefinition + var id roledefinitions.ScopedRoleDefinitionId + var role roledefinitions.RoleDefinition if config.Name != "" { // Accounting for eventual consistency deadline, ok := ctx.Deadline() @@ -163,58 +164,73 @@ func (a RoleDefinitionDataSource) Read() sdk.ResourceFunc { return fmt.Errorf("internal error: context had no deadline") } err := pluginsdk.Retry(time.Until(deadline), func() *pluginsdk.RetryError { - roleDefinitions, err := client.List(ctx, config.Scope, fmt.Sprintf("roleName eq '%s'", config.Name)) + roleDefinitions, err := client.List(ctx, commonids.NewScopeID(config.Scope), roledefinitions.ListOperationOptions{ + Filter: pointer.To(fmt.Sprintf("roleName eq '%s'", config.Name)), + }) if err != nil { return pluginsdk.NonRetryableError(fmt.Errorf("loading Role Definition List: %+v", err)) } - if len(roleDefinitions.Values()) != 1 { + if roleDefinitions.Model == nil { + return pluginsdk.RetryableError(fmt.Errorf("loading Role Definition List: model was nil")) + } + if len(*roleDefinitions.Model) != 1 { return pluginsdk.RetryableError(fmt.Errorf("loading Role Definition List: could not find role '%s'", config.Name)) } - if roleDefinitions.Values()[0].ID == nil { - return pluginsdk.NonRetryableError(fmt.Errorf("loading Role Definition List: values[0].ID is nil '%s'", config.Name)) + if (*roleDefinitions.Model)[0].Name == nil { + return pluginsdk.NonRetryableError(fmt.Errorf("loading Role Definition List: values[0].NameD is nil '%s'", config.Name)) } - defId = *roleDefinitions.Values()[0].ID - role, err = client.GetByID(ctx, defId) - if err != nil { - return pluginsdk.NonRetryableError(fmt.Errorf("getting Role Definition by ID %s: %+v", defId, err)) - } + defId = *(*roleDefinitions.Model)[0].Id + id = roledefinitions.NewScopedRoleDefinitionID(config.Scope, *(*roleDefinitions.Model)[0].Name) return nil }) if err != nil { return err } } else { - var err error - role, err = client.Get(ctx, config.Scope, defId) - if err != nil { - return fmt.Errorf("loading Role Definition: %+v", err) - } + id = roledefinitions.NewScopedRoleDefinitionID(config.Scope, defId) + } + + resp, err := client.Get(ctx, id) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", id, err) + } + if resp.Model == nil { + return fmt.Errorf("retrieving %s: `Model` was nil", id) + } + + role = *resp.Model + + if role.Id == nil { + return fmt.Errorf("retrieving %s: `Id` was nil", id) } state := RoleDefinitionDataSourceModel{ - Scope: config.Scope, + Scope: id.Scope, RoleDefinitionId: defId, } + if props := role.Properties; props != nil { + state.Name = pointer.From(props.RoleName) + state.Type = pointer.From(props.Type) + state.Description = pointer.From(props.Description) + state.Permissions = flattenDataSourceRoleDefinitionPermissions(props.Permissions) + state.AssignableScopes = pointer.From(props.AssignableScopes) + } - state.Name = pointer.From(role.RoleName) - state.Type = pointer.From(role.Type) - state.Description = pointer.From(role.Description) - state.Permissions = flattenDataSourceRoleDefinitionPermissions(role.Permissions) - state.AssignableScopes = pointer.From(role.AssignableScopes) - - metadata.ResourceData.SetId(*role.ID) + // The sdk managed id start with two "/" when scope is tenant level (empty). + // So we use the id from response without parsing and reformating it. + // Tracked on https://github.com/hashicorp/pandora/issues/3257 + metadata.ResourceData.SetId(*role.Id) return metadata.Encode(&state) }, } } -func flattenDataSourceRoleDefinitionPermissions(input *[]authorization.Permission) []PermissionDataSourceModel { +func flattenDataSourceRoleDefinitionPermissions(input *[]roledefinitions.Permission) []PermissionDataSourceModel { permissions := make([]PermissionDataSourceModel, 0) if input == nil { return permissions } - for _, permission := range *input { permissions = append(permissions, PermissionDataSourceModel{ Actions: pointer.From(permission.Actions), @@ -223,6 +239,5 @@ func flattenDataSourceRoleDefinitionPermissions(input *[]authorization.Permissio NotDataActions: pointer.From(permission.NotDataActions), }) } - return permissions } diff --git a/internal/services/authorization/role_definition_resource.go b/internal/services/authorization/role_definition_resource.go index a32613a1ea24..c1a0cff96234 100644 --- a/internal/services/authorization/role_definition_resource.go +++ b/internal/services/authorization/role_definition_resource.go @@ -9,9 +9,10 @@ import ( "log" "time" - "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2020-04-01-preview/authorization" // nolint: staticcheck "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions" "github.com/hashicorp/go-uuid" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/services/authorization/azuresdkhacks" @@ -19,7 +20,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/services/authorization/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" ) type RoleDefinitionResource struct{} @@ -171,55 +171,58 @@ func (r RoleDefinitionResource) Create() sdk.ResourceFunc { return fmt.Errorf("decoding %+v", err) } - roleDefinitionId := config.RoleDefinitionId - if roleDefinitionId == "" { + roleId := config.RoleDefinitionId + if roleId == "" { uuid, err := uuid.GenerateUUID() if err != nil { return fmt.Errorf("generating UUID for Role Assignment: %+v", err) } - roleDefinitionId = uuid + roleId = uuid } - existing, err := client.Get(ctx, config.Scope, roleDefinitionId) - if err != nil && !utils.ResponseWasNotFound(existing.Response) { + id := roledefinitions.NewScopedRoleDefinitionID(config.Scope, roleId) + + existing, err := client.Get(ctx, id) + if err != nil && !response.WasNotFound(existing.HttpResponse) { return fmt.Errorf("checking for presence of existing Role Definition ID for %q (Scope %q)", config.Name, config.Scope) } - if !utils.ResponseWasNotFound(existing.Response) { + if !response.WasNotFound(existing.HttpResponse) { importID := parse.RoleDefinitionID{ - RoleID: roleDefinitionId, + RoleID: roleId, Scope: config.Scope, } return metadata.ResourceRequiresImport(r.ResourceType(), importID) } - properties := authorization.RoleDefinition{ - RoleDefinitionProperties: &authorization.RoleDefinitionProperties{ + properties := roledefinitions.RoleDefinition{ + Properties: &roledefinitions.RoleDefinitionProperties{ RoleName: &config.Name, Description: &config.Description, - RoleType: pointer.To("CustomRole"), + Type: pointer.To("CustomRole"), Permissions: pointer.To(expandRoleDefinitionPermissions(config.Permissions)), AssignableScopes: pointer.To(expandRoleDefinitionAssignableScopes(config)), }, } - if _, err := client.CreateOrUpdate(ctx, config.Scope, roleDefinitionId, properties); err != nil { + if _, err := client.CreateOrUpdate(ctx, id, properties); err != nil { return err } - read, err := client.Get(ctx, config.Scope, roleDefinitionId) + read, err := client.Get(ctx, id) if err != nil { return err } - if read.ID == nil || *read.ID == "" { + + if read.Model == nil || read.Model.Id == nil || *read.Model.Id == "" { return fmt.Errorf("cannot read Role Definition ID for %q (Scope %q)", config.Name, config.Scope) } - parsedId := parse.RoleDefinitionID{ - RoleID: roleDefinitionId, + stateId := parse.RoleDefinitionID{ + RoleID: roleId, Scope: config.Scope, - ResourceID: *read.ID, + ResourceID: *read.Model.Id, } - metadata.SetID(parsedId) + metadata.SetID(stateId) return nil }, } @@ -231,33 +234,39 @@ func (r RoleDefinitionResource) Read() sdk.ResourceFunc { Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { client := metadata.Client.Authorization.RoleDefinitionsClient - id, err := parse.RoleDefinitionId(metadata.ResourceData.Id()) + stateId, err := parse.RoleDefinitionId(metadata.ResourceData.Id()) if err != nil { return err } - resp, err := client.Get(ctx, id.Scope, id.RoleID) + id := roledefinitions.NewScopedRoleDefinitionID(stateId.Scope, stateId.RoleID) + + resp, err := client.Get(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return metadata.MarkAsGone(id) + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(stateId) } - return fmt.Errorf("retrieving %s: %+v", id, err) + return fmt.Errorf("retrieving %s: %+v", stateId, err) } state := RoleDefinitionModel{ - Scope: id.Scope, - RoleDefinitionId: id.RoleID, + Scope: stateId.Scope, + RoleDefinitionId: stateId.RoleID, + } + + if model := resp.Model; model != nil { + // The Azure resource id of Role Definition is not as same as the one we used to create it. + // So we read from the response. + state.RoleDefinitionResourceId = pointer.From(model.Id) + if prop := model.Properties; prop != nil { + state.Name = pointer.From(model.Properties.RoleName) + state.Description = pointer.From(prop.Description) + state.Permissions = flattenRoleDefinitionPermissions(prop.Permissions) + state.AssignableScopes = pointer.From(prop.AssignableScopes) + } } - // The Azure resource id of Role Definition is not as same as the one we used to create it. - // So we read from the response. - state.RoleDefinitionResourceId = pointer.From(resp.ID) - state.Name = pointer.From(resp.RoleName) - state.Description = pointer.From(resp.Description) - state.Permissions = flattenRoleDefinitionPermissions(resp.Permissions) - state.AssignableScopes = pointer.From(resp.AssignableScopes) - return metadata.Encode(&state) }, } @@ -268,79 +277,81 @@ func (r RoleDefinitionResource) Update() sdk.ResourceFunc { Timeout: 60 * time.Minute, Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { sdkClient := metadata.Client.Authorization.RoleDefinitionsClient - client := azuresdkhacks.NewRoleDefinitionsWorkaroundClient(sdkClient) + client := azuresdkhacks.NewRoleDefinitionsWorkaroundClient(sdkClient.Client) - id, err := parse.RoleDefinitionId(metadata.ResourceData.Id()) + stateId, err := parse.RoleDefinitionId(metadata.ResourceData.Id()) if err != nil { return err } + id := roledefinitions.NewScopedRoleDefinitionID(stateId.Scope, stateId.RoleID) + var config RoleDefinitionModel if err := metadata.Decode(&config); err != nil { return err } - exisiting, err := client.Get(ctx, id.Scope, id.RoleID) + exisiting, err := client.Get(ctx, id) if err != nil { - return fmt.Errorf("retrieving %s: %+v", id, err) - } - - permissions := []authorization.Permission{} - if config.Permissions != nil { - for _, permission := range *exisiting.Permissions { - permissions = append(permissions, authorization.Permission{ - Actions: permission.Actions, - DataActions: permission.DataActions, - NotActions: permission.NotActions, - NotDataActions: permission.NotDataActions, - }) - } + return fmt.Errorf("retrieving %s: %+v", stateId, err) } - update := authorization.RoleDefinition{ - RoleDefinitionProperties: &authorization.RoleDefinitionProperties{ - RoleName: exisiting.RoleName, - Description: exisiting.Description, - RoleType: exisiting.RoleType, - Permissions: &permissions, - AssignableScopes: exisiting.AssignableScopes, - }, + if exisiting.Model == nil { + return fmt.Errorf("retrieving %s: model was nil", stateId) } + model := *exisiting.Model + + if model.Properties == nil { + return fmt.Errorf("retrieving %s: properties was nil", stateId) + } + + props := *model.Properties + if metadata.ResourceData.HasChange("name") { - update.RoleDefinitionProperties.RoleName = &config.Name + props.RoleName = &config.Name } if metadata.ResourceData.HasChange("description") { - update.RoleDefinitionProperties.Description = &config.Description + props.Description = &config.Description } if metadata.ResourceData.HasChange("permissions") { - update.RoleDefinitionProperties.Permissions = pointer.To(expandRoleDefinitionPermissions(config.Permissions)) + props.Permissions = pointer.To(expandRoleDefinitionPermissions(config.Permissions)) } if metadata.ResourceData.HasChange("assignable_scopes") { - update.RoleDefinitionProperties.AssignableScopes = pointer.To(expandRoleDefinitionAssignableScopes(config)) + props.AssignableScopes = pointer.To(expandRoleDefinitionAssignableScopes(config)) } - resp, err := client.CreateOrUpdate(ctx, id.Scope, id.RoleID, update) + model.Properties = &props + + resp, err := client.CreateOrUpdate(ctx, id, model) if err != nil { - return fmt.Errorf("updating %s: %+v", id, err) + return fmt.Errorf("updating %s: %+v", stateId, err) + } + + if resp.Model == nil { + return fmt.Errorf("updating %s: model was nil", stateId) } - updatedOn := resp.RoleDefinitionProperties.UpdatedOn + if resp.Model.Properties == nil { + return fmt.Errorf("updating %s: properties was nil", stateId) + } + + updatedOn := resp.Model.Properties.UpdatedOn if updatedOn == nil { - return fmt.Errorf("updating Role Definition %q (Scope %q): `properties.UpdatedOn` was nil", id.RoleID, id.Scope) + return fmt.Errorf("updating Role Definition %q (Scope %q): `properties.UpdatedOn` was nil", stateId.RoleID, stateId.Scope) } if updatedOn == nil { - return fmt.Errorf("updating %s: `properties.UpdatedOn` was nil", id) + return fmt.Errorf("updating %s: `properties.UpdatedOn` was nil", stateId) } // "Updating" a role definition actually creates a new one and these get consolidated a few seconds later // where the "create date" and "update date" match for the newly created record // but eventually switch to being the old create date and the new update date // ergo we can can for the old create date and the new updated date - log.Printf("[DEBUG] Waiting for %s to settle down..", id) + log.Printf("[DEBUG] Waiting for %s to settle down..", stateId) deadline, ok := ctx.Deadline() if !ok { return fmt.Errorf("internal error: context had no deadline") @@ -351,11 +362,11 @@ func (r RoleDefinitionResource) Update() sdk.ResourceFunc { MinTimeout: 10 * time.Second, Pending: []string{"Pending"}, Target: []string{"Updated"}, - Refresh: roleDefinitionEventualConsistencyUpdate(ctx, client, *id, *updatedOn), + Refresh: roleDefinitionEventualConsistencyUpdate(ctx, client, id, *updatedOn), Timeout: time.Until(deadline), } if _, err := stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for %s to settle down: %+v", id, err) + return fmt.Errorf("waiting for %s to settle down: %+v", stateId, err) } return nil @@ -369,17 +380,19 @@ func (r RoleDefinitionResource) Delete() sdk.ResourceFunc { Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { client := metadata.Client.Authorization.RoleDefinitionsClient - id, err := parse.RoleDefinitionId(metadata.ResourceData.Id()) + stateId, err := parse.RoleDefinitionId(metadata.ResourceData.Id()) if err != nil { return err } - resp, err := client.Delete(ctx, id.Scope, id.RoleID) + id := roledefinitions.NewScopedRoleDefinitionID(stateId.Scope, stateId.RoleID) + + resp, err := client.Delete(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { return nil } - return fmt.Errorf("deleting %s: %+v", id, err) + return fmt.Errorf("deleting %s: %+v", stateId, err) } // Deletes are not instant and can take time to propagate @@ -395,14 +408,14 @@ func (r RoleDefinitionResource) Delete() sdk.ResourceFunc { "Deleted", "NotFound", }, - Refresh: roleDefinitionDeleteStateRefreshFunc(ctx, client, *id), + Refresh: roleDefinitionDeleteStateRefreshFunc(ctx, client, id), MinTimeout: 10 * time.Second, ContinuousTargetOccurence: 20, Timeout: time.Until(deadline), } if _, err := stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for delete on Role Definition %s to complete", id) + return fmt.Errorf("waiting for delete on Role Definition %s to complete", stateId) } return nil @@ -419,20 +432,23 @@ func (RoleDefinitionResource) StateUpgraders() sdk.StateUpgradeData { } } -func roleDefinitionEventualConsistencyUpdate(ctx context.Context, client azuresdkhacks.RoleDefinitionsWorkaroundClient, id parse.RoleDefinitionID, updateRequestDate string) pluginsdk.StateRefreshFunc { +func roleDefinitionEventualConsistencyUpdate(ctx context.Context, client azuresdkhacks.RoleDefinitionsWorkaroundClient, id roledefinitions.ScopedRoleDefinitionId, updateRequestDate string) pluginsdk.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := client.Get(ctx, id.Scope, id.RoleID) + resp, err := client.Get(ctx, id) if err != nil { return resp, "Failed", err } - if resp.RoleDefinitionProperties == nil { + if resp.Model == nil { + return resp, "Failed", fmt.Errorf("`model` was nil") + } + if resp.Model.Properties == nil { return resp, "Failed", fmt.Errorf("`properties` was nil") } - if resp.RoleDefinitionProperties.CreatedOn == nil { + if resp.Model.Properties.CreatedOn == nil { return resp, "Failed", fmt.Errorf("`properties.CreatedOn` was nil") } - if resp.RoleDefinitionProperties.UpdatedOn == nil { + if resp.Model.Properties.UpdatedOn == nil { return resp, "Failed", fmt.Errorf("`properties.UpdatedOn` was nil") } @@ -441,12 +457,12 @@ func roleDefinitionEventualConsistencyUpdate(ctx context.Context, client azuresd return nil, "", fmt.Errorf("parsing time from update request: %+v", err) } - respCreatedOn, err := time.Parse(time.RFC3339, *resp.RoleDefinitionProperties.CreatedOn) + respCreatedOn, err := time.Parse(time.RFC3339, *resp.Model.Properties.CreatedOn) if err != nil { return nil, "", fmt.Errorf("parsing time for createdOn from update request: %+v", err) } - respUpdatedOn, err := time.Parse(time.RFC3339, *resp.RoleDefinitionProperties.UpdatedOn) + respUpdatedOn, err := time.Parse(time.RFC3339, *resp.Model.Properties.UpdatedOn) if err != nil { return nil, "", fmt.Errorf("parsing time for updatedOn from update request: %+v", err) } @@ -465,14 +481,14 @@ func roleDefinitionEventualConsistencyUpdate(ctx context.Context, client azuresd } } -func expandRoleDefinitionPermissions(input []PermissionModel) []authorization.Permission { - output := make([]authorization.Permission, 0) +func expandRoleDefinitionPermissions(input []PermissionModel) []roledefinitions.Permission { + output := make([]roledefinitions.Permission, 0) if len(input) == 0 { return output } for _, v := range input { - permission := authorization.Permission{} + permission := roledefinitions.Permission{} permission.Actions = &v.Actions permission.DataActions = &v.DataActions @@ -497,7 +513,7 @@ func expandRoleDefinitionAssignableScopes(config RoleDefinitionModel) []string { return scopes } -func flattenRoleDefinitionPermissions(input *[]authorization.Permission) []PermissionModel { +func flattenRoleDefinitionPermissions(input *[]roledefinitions.Permission) []PermissionModel { permissions := make([]PermissionModel, 0) if input == nil { return permissions @@ -515,11 +531,11 @@ func flattenRoleDefinitionPermissions(input *[]authorization.Permission) []Permi return permissions } -func roleDefinitionDeleteStateRefreshFunc(ctx context.Context, client *authorization.RoleDefinitionsClient, id parse.RoleDefinitionID) pluginsdk.StateRefreshFunc { +func roleDefinitionDeleteStateRefreshFunc(ctx context.Context, client *roledefinitions.RoleDefinitionsClient, id roledefinitions.ScopedRoleDefinitionId) pluginsdk.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := client.Get(ctx, id.Scope, id.RoleID) + resp, err := client.Get(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { return resp, "NotFound", nil } return nil, "Error", err diff --git a/internal/services/authorization/role_definition_resource_test.go b/internal/services/authorization/role_definition_resource_test.go index 4dfd9a23180f..7e1d0f12225b 100644 --- a/internal/services/authorization/role_definition_resource_test.go +++ b/internal/services/authorization/role_definition_resource_test.go @@ -9,11 +9,13 @@ import ( "testing" "github.com/google/uuid" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions" "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 RoleDefinitionResource struct{} @@ -191,17 +193,18 @@ func TestAccRoleDefinition_noAssignableScope(t *testing.T) { func (RoleDefinitionResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { scope := state.Attributes["scope"] - roleDefinitionId := state.Attributes["role_definition_id"] + roleId := state.Attributes["role_definition_id"] - resp, err := client.Authorization.RoleDefinitionsClient.Get(ctx, scope, roleDefinitionId) + id := roledefinitions.NewScopedRoleDefinitionID(scope, roleId) + resp, err := client.Authorization.RoleDefinitionsClient.Get(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return utils.Bool(false), nil + if response.WasNotFound(resp.HttpResponse) { + return pointer.To(false), nil } - return nil, fmt.Errorf("Bad: Get on roleDefinitionsClient: %+v", err) + return nil, fmt.Errorf("reading %s: %+v", id, err) } - return utils.Bool(true), nil + return pointer.To(true), nil } func (RoleDefinitionResource) basic(id string, data acceptance.TestData) string { diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/README.md new file mode 100644 index 000000000000..b4935c0a5115 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/README.md @@ -0,0 +1,90 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions` Documentation + +The `roledefinitions` SDK allows for interaction with the Azure Resource Manager Service `authorization` (API Version `2018-01-01-preview`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions" +``` + + +### Client Initialization + +```go +client := roledefinitions.NewRoleDefinitionsClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `RoleDefinitionsClient.CreateOrUpdate` + +```go +ctx := context.TODO() +id := roledefinitions.NewScopedRoleDefinitionID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleDefinitionIdValue") + +payload := roledefinitions.RoleDefinition{ + // ... +} + + +read, err := client.CreateOrUpdate(ctx, id, payload) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleDefinitionsClient.Delete` + +```go +ctx := context.TODO() +id := roledefinitions.NewScopedRoleDefinitionID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleDefinitionIdValue") + +read, err := client.Delete(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleDefinitionsClient.Get` + +```go +ctx := context.TODO() +id := roledefinitions.NewScopedRoleDefinitionID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleDefinitionIdValue") + +read, err := client.Get(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleDefinitionsClient.List` + +```go +ctx := context.TODO() +id := roledefinitions.NewScopeID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group") + +// alternatively `client.List(ctx, id, roledefinitions.DefaultListOperationOptions())` can be used to do batched pagination +items, err := client.ListComplete(ctx, id, roledefinitions.DefaultListOperationOptions()) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/client.go new file mode 100644 index 000000000000..b4b1a6f36991 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/client.go @@ -0,0 +1,26 @@ +package roledefinitions + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + sdkEnv "github.com/hashicorp/go-azure-sdk/sdk/environments" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleDefinitionsClient struct { + Client *resourcemanager.Client +} + +func NewRoleDefinitionsClientWithBaseURI(sdkApi sdkEnv.Api) (*RoleDefinitionsClient, error) { + client, err := resourcemanager.NewResourceManagerClient(sdkApi, "roledefinitions", defaultApiVersion) + if err != nil { + return nil, fmt.Errorf("instantiating RoleDefinitionsClient: %+v", err) + } + + return &RoleDefinitionsClient{ + Client: client, + }, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/id_scopedroledefinition.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/id_scopedroledefinition.go new file mode 100644 index 000000000000..b89ef3f30096 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/id_scopedroledefinition.go @@ -0,0 +1,115 @@ +package roledefinitions + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +var _ resourceids.ResourceId = &ScopedRoleDefinitionId{} + +// ScopedRoleDefinitionId is a struct representing the Resource ID for a Scoped Role Definition +type ScopedRoleDefinitionId struct { + Scope string + RoleDefinitionId string +} + +// NewScopedRoleDefinitionID returns a new ScopedRoleDefinitionId struct +func NewScopedRoleDefinitionID(scope string, roleDefinitionId string) ScopedRoleDefinitionId { + return ScopedRoleDefinitionId{ + Scope: scope, + RoleDefinitionId: roleDefinitionId, + } +} + +// ParseScopedRoleDefinitionID parses 'input' into a ScopedRoleDefinitionId +func ParseScopedRoleDefinitionID(input string) (*ScopedRoleDefinitionId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedRoleDefinitionId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedRoleDefinitionId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseScopedRoleDefinitionIDInsensitively parses 'input' case-insensitively into a ScopedRoleDefinitionId +// note: this method should only be used for API response data and not user input +func ParseScopedRoleDefinitionIDInsensitively(input string) (*ScopedRoleDefinitionId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedRoleDefinitionId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedRoleDefinitionId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *ScopedRoleDefinitionId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.Scope, ok = input.Parsed["scope"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "scope", input) + } + + if id.RoleDefinitionId, ok = input.Parsed["roleDefinitionId"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "roleDefinitionId", input) + } + + return nil +} + +// ValidateScopedRoleDefinitionID checks that 'input' can be parsed as a Scoped Role Definition ID +func ValidateScopedRoleDefinitionID(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 := ParseScopedRoleDefinitionID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Scoped Role Definition ID +func (id ScopedRoleDefinitionId) ID() string { + fmtString := "/%s/providers/Microsoft.Authorization/roleDefinitions/%s" + return fmt.Sprintf(fmtString, strings.TrimPrefix(id.Scope, "/"), id.RoleDefinitionId) +} + +// Segments returns a slice of Resource ID Segments which comprise this Scoped Role Definition ID +func (id ScopedRoleDefinitionId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.ScopeSegment("scope", "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftAuthorization", "Microsoft.Authorization", "Microsoft.Authorization"), + resourceids.StaticSegment("staticRoleDefinitions", "roleDefinitions", "roleDefinitions"), + resourceids.UserSpecifiedSegment("roleDefinitionId", "roleDefinitionIdValue"), + } +} + +// String returns a human-readable description of this Scoped Role Definition ID +func (id ScopedRoleDefinitionId) String() string { + components := []string{ + fmt.Sprintf("Scope: %q", id.Scope), + fmt.Sprintf("Role Definition: %q", id.RoleDefinitionId), + } + return fmt.Sprintf("Scoped Role Definition (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_createorupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_createorupdate.go new file mode 100644 index 000000000000..02773b79de3d --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_createorupdate.go @@ -0,0 +1,55 @@ +package roledefinitions + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CreateOrUpdateOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleDefinition +} + +// CreateOrUpdate ... +func (c RoleDefinitionsClient) CreateOrUpdate(ctx context.Context, id ScopedRoleDefinitionId, input RoleDefinition) (result CreateOrUpdateOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusCreated, + }, + HttpMethod: http.MethodPut, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + if err = resp.Unmarshal(&result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_delete.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_delete.go new file mode 100644 index 000000000000..36398d10b684 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_delete.go @@ -0,0 +1,52 @@ +package roledefinitions + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleDefinition +} + +// Delete ... +func (c RoleDefinitionsClient) Delete(ctx context.Context, id ScopedRoleDefinitionId) (result DeleteOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusNoContent, + http.StatusOK, + }, + HttpMethod: http.MethodDelete, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + if err = resp.Unmarshal(&result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_get.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_get.go new file mode 100644 index 000000000000..8dbb310475c6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_get.go @@ -0,0 +1,51 @@ +package roledefinitions + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleDefinition +} + +// Get ... +func (c RoleDefinitionsClient) Get(ctx context.Context, id ScopedRoleDefinitionId) (result GetOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + if err = resp.Unmarshal(&result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_list.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_list.go new file mode 100644 index 000000000000..e58c6664b3e2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/method_list.go @@ -0,0 +1,120 @@ +package roledefinitions + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]RoleDefinition +} + +type ListCompleteResult struct { + LatestHttpResponse *http.Response + Items []RoleDefinition +} + +type ListOperationOptions struct { + Filter *string +} + +func DefaultListOperationOptions() ListOperationOptions { + return ListOperationOptions{} +} + +func (o ListOperationOptions) ToHeaders() *client.Headers { + out := client.Headers{} + + return &out +} + +func (o ListOperationOptions) ToOData() *odata.Query { + out := odata.Query{} + return &out +} + +func (o ListOperationOptions) ToQuery() *client.QueryParams { + out := client.QueryParams{} + if o.Filter != nil { + out.Append("$filter", fmt.Sprintf("%v", *o.Filter)) + } + return &out +} + +// List ... +func (c RoleDefinitionsClient) List(ctx context.Context, id commonids.ScopeId, options ListOperationOptions) (result ListOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: fmt.Sprintf("%s/providers/Microsoft.Authorization/roleDefinitions", id.ID()), + OptionsObject: options, + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]RoleDefinition `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListComplete retrieves all the results into a single object +func (c RoleDefinitionsClient) ListComplete(ctx context.Context, id commonids.ScopeId, options ListOperationOptions) (ListCompleteResult, error) { + return c.ListCompleteMatchingPredicate(ctx, id, options, RoleDefinitionOperationPredicate{}) +} + +// ListCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c RoleDefinitionsClient) ListCompleteMatchingPredicate(ctx context.Context, id commonids.ScopeId, options ListOperationOptions, predicate RoleDefinitionOperationPredicate) (result ListCompleteResult, err error) { + items := make([]RoleDefinition, 0) + + resp, err := c.List(ctx, id, options) + if err != nil { + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_permission.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_permission.go new file mode 100644 index 000000000000..b8e01a191420 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_permission.go @@ -0,0 +1,11 @@ +package roledefinitions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Permission struct { + Actions *[]string `json:"actions,omitempty"` + DataActions *[]string `json:"dataActions,omitempty"` + NotActions *[]string `json:"notActions,omitempty"` + NotDataActions *[]string `json:"notDataActions,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_roledefinition.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_roledefinition.go new file mode 100644 index 000000000000..6f08f38cbc71 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_roledefinition.go @@ -0,0 +1,11 @@ +package roledefinitions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleDefinition struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *RoleDefinitionProperties `json:"properties,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_roledefinitionproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_roledefinitionproperties.go new file mode 100644 index 000000000000..a63082845507 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/model_roledefinitionproperties.go @@ -0,0 +1,12 @@ +package roledefinitions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleDefinitionProperties struct { + AssignableScopes *[]string `json:"assignableScopes,omitempty"` + Description *string `json:"description,omitempty"` + Permissions *[]Permission `json:"permissions,omitempty"` + RoleName *string `json:"roleName,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/predicates.go new file mode 100644 index 000000000000..9441f95eaf76 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/predicates.go @@ -0,0 +1,27 @@ +package roledefinitions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleDefinitionOperationPredicate struct { + Id *string + Name *string + Type *string +} + +func (p RoleDefinitionOperationPredicate) Matches(input RoleDefinition) bool { + + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { + return false + } + + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/version.go new file mode 100644 index 000000000000..dea43e714b28 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions/version.go @@ -0,0 +1,12 @@ +package roledefinitions + +import "fmt" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2018-01-01-preview" + +func userAgent() string { + return fmt.Sprintf("hashicorp/go-azure-sdk/roledefinitions/%s", defaultApiVersion) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2d25303f30ba..08d52637027f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -221,6 +221,7 @@ github.com/hashicorp/go-azure-sdk/resource-manager/applicationinsights/2022-04-0 github.com/hashicorp/go-azure-sdk/resource-manager/applicationinsights/2022-06-15/webtestsapis github.com/hashicorp/go-azure-sdk/resource-manager/appplatform/2023-11-01-preview/appplatform github.com/hashicorp/go-azure-sdk/resource-manager/attestation/2020-10-01/attestationproviders +github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2018-01-01-preview/roledefinitions github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleassignmentscheduleinstances 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