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

SDK Migration 04: migrate administrativeunits to go-azure-sdk #1478

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ package administrativeunits
import (
"context"
"fmt"
"net/http"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/directory/stable/administrativeunit"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/directory/stable/administrativeunitmember"
"github.com/hashicorp/go-azure-sdk/sdk/odata"
"github.com/hashicorp/terraform-provider-azuread/internal/clients"
"github.com/hashicorp/terraform-provider-azuread/internal/tf"
"github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azuread/internal/tf/validation"
"github.com/manicminer/hamilton/msgraph"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/validation"
)

func administrativeUnitDataSource() *pluginsdk.Resource {
Expand Down Expand Up @@ -70,9 +73,10 @@ func administrativeUnitDataSource() *pluginsdk.Resource {
}

func administrativeUnitDataSourceRead(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics {
client := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitsClient
client := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitClient
memberClient := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitMemberClient

var administrativeUnit msgraph.AdministrativeUnit
var administrativeUnit stable.AdministrativeUnit
var displayName, objectId string

if v, ok := d.GetOk("display_name"); ok {
Expand All @@ -83,48 +87,57 @@ func administrativeUnitDataSourceRead(ctx context.Context, d *pluginsdk.Resource
}

if displayName != "" {
filter := fmt.Sprintf("displayName eq '%s'", displayName)
administrativeUnits, _, err := client.List(ctx, odata.Query{Filter: filter})
if err != nil || administrativeUnits == nil {
return tf.ErrorDiagPathF(err, "display_name", "No administrative unit found matching specified filter (%s)", filter)
options := administrativeunit.ListAdministrativeUnitsOperationOptions{
Filter: pointer.To(fmt.Sprintf("displayName eq '%s'", odata.EscapeSingleQuote(displayName))),
}
resp, err := client.ListAdministrativeUnits(ctx, options)
if err != nil || resp.Model == nil {
return tf.ErrorDiagPathF(err, "display_name", "No administrative unit found matching specified filter (%s)", *options.Filter)
}

count := len(*administrativeUnits)
count := len(*resp.Model)
if count > 1 {
return tf.ErrorDiagPathF(err, "display_name", "More than one administrative unit found matching specified filter (%s)", filter)
return tf.ErrorDiagPathF(err, "display_name", "More than one administrative unit found matching specified filter (%s)", *options.Filter)
} else if count == 0 {
return tf.ErrorDiagPathF(err, "display_name", "No administrative unit found matching specified filter (%s)", filter)
return tf.ErrorDiagPathF(err, "display_name", "No administrative unit found matching specified filter (%s)", *options.Filter)
}

administrativeUnit = (*administrativeUnits)[0]
administrativeUnit = (*resp.Model)[0]
} else if objectId != "" {
au, status, err := client.Get(ctx, objectId, odata.Query{})
resp, err := client.GetAdministrativeUnit(ctx, stable.NewDirectoryAdministrativeUnitID(objectId), administrativeunit.DefaultGetAdministrativeUnitOperationOptions())
if err != nil {
if status == http.StatusNotFound {
if response.WasNotFound(resp.HttpResponse) {
return tf.ErrorDiagPathF(nil, "object_id", "No administrative unit found with object ID: %q", objectId)
}
return tf.ErrorDiagF(err, "Retrieving administrative unit with object ID: %q", d.Id())
}

administrativeUnit = *au
administrativeUnit = *resp.Model
}

if administrativeUnit.ID == nil {
if administrativeUnit.Id == nil {
return tf.ErrorDiagF(fmt.Errorf("API returned administrative unit with nil object ID"), "Bad API response")
}

d.SetId(*administrativeUnit.ID)
d.SetId(*administrativeUnit.Id)

tf.Set(d, "description", administrativeUnit.Description)
tf.Set(d, "display_name", administrativeUnit.DisplayName)
tf.Set(d, "object_id", administrativeUnit.ID)
tf.Set(d, "visibility", administrativeUnit.Visibility)
tf.Set(d, "description", administrativeUnit.Description.GetOrZero())
tf.Set(d, "display_name", administrativeUnit.DisplayName.GetOrZero())
tf.Set(d, "object_id", pointer.From(administrativeUnit.Id))
tf.Set(d, "visibility", administrativeUnit.Visibility.GetOrZero())

members, _, err := client.ListMembers(ctx, *administrativeUnit.ID)
membersResp, err := memberClient.ListAdministrativeUnitMembers(ctx, stable.NewDirectoryAdministrativeUnitID(*administrativeUnit.Id), administrativeunitmember.DefaultListAdministrativeUnitMembersOperationOptions())
if err != nil {
return tf.ErrorDiagPathF(err, "members", "Could not retrieve members for administrative unit with object ID %q", d.Id())
}
tf.Set(d, "members", members)

memberIds := make([]string, 0)
if membersResp.Model != nil {
for _, member := range *membersResp.Model {
memberIds = append(memberIds, pointer.From(member.DirectoryObject().Id))
}
}
tf.Set(d, "members", memberIds)

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ import (
"errors"
"fmt"
"log"
"net/http"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-sdk/sdk/odata"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/directory/stable/administrativeunit"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/directory/stable/administrativeunitmember"
"github.com/hashicorp/terraform-provider-azuread/internal/clients"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/consistency"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/validation"
"github.com/hashicorp/terraform-provider-azuread/internal/services/administrativeunits/parse"
"github.com/hashicorp/terraform-provider-azuread/internal/tf"
"github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azuread/internal/tf/validation"
"github.com/manicminer/hamilton/msgraph"
)

func administrativeUnitMemberResource() *pluginsdk.Resource {
Expand Down Expand Up @@ -60,44 +61,35 @@ func administrativeUnitMemberResource() *pluginsdk.Resource {
}

func administrativeUnitMemberResourceCreate(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics {
client := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitsClient
directoryObjectsClient := meta.(*clients.Client).AdministrativeUnits.DirectoryObjectsClient
tenantId := meta.(*clients.Client).TenantID
client := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitClient
memberClient := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitMemberClient

id := parse.NewAdministrativeUnitMemberID(d.Get("administrative_unit_object_id").(string), d.Get("member_object_id").(string))

tf.LockByName(administrativeUnitResourceName, id.AdministrativeUnitId)
defer tf.UnlockByName(administrativeUnitResourceName, id.AdministrativeUnitId)

administrativeUnit, status, err := client.Get(ctx, id.AdministrativeUnitId, odata.Query{})
resp, err := client.GetAdministrativeUnit(ctx, stable.NewDirectoryAdministrativeUnitID(id.AdministrativeUnitId), administrativeunit.DefaultGetAdministrativeUnitOperationOptions())
if err != nil {
if status == http.StatusNotFound {
if response.WasNotFound(resp.HttpResponse) {
return tf.ErrorDiagPathF(nil, "object_id", "Administrative unit with object ID %q was not found", id.AdministrativeUnitId)
}
return tf.ErrorDiagPathF(err, "object_id", "Retrieving administrative unit with object ID: %q", id.AdministrativeUnitId)
}

client.BaseClient.DisableRetries = true
if _, status, err = client.GetMember(ctx, id.AdministrativeUnitId, id.MemberId); err == nil {
return tf.ImportAsExistsDiag("azuread_administrative_unit_member", id.String())
} else if status != http.StatusNotFound {
if member, err := administrativeUnitGetMember(ctx, memberClient, id.AdministrativeUnitId, id.MemberId); err != nil {
return tf.ErrorDiagF(err, "Checking for existing membership of member %q for administrative unit with object ID: %q", id.MemberId, id.AdministrativeUnitId)
} else if member != nil {
return tf.ImportAsExistsDiag("azuread_administrative_unit_member", id.String())
}
client.BaseClient.DisableRetries = false

memberObject, _, err := directoryObjectsClient.Get(ctx, id.MemberId, odata.Query{})
if err != nil {
return tf.ErrorDiagF(err, "Could not retrieve member principal object %q", id.MemberId)
}
if memberObject == nil {
return tf.ErrorDiagF(errors.New("returned memberObject was nil"), "Could not retrieve member principal object %q", id.MemberId)
}
memberObject.ODataId = (*odata.Id)(pointer.To(fmt.Sprintf("%s/v1.0/%s/directoryObjects/%s",
client.BaseClient.Endpoint, tenantId, id.MemberId)))
memberId := stable.NewDirectoryObjectID(id.MemberId)

members := &msgraph.Members{*memberObject}
addMemberProperties := stable.ReferenceCreate{
ODataId: pointer.To(client.Client.BaseUri + memberId.ID()),
}

if _, err := client.AddMembers(ctx, *administrativeUnit.ID, members); err != nil {
if _, err = memberClient.AddAdministrativeUnitMemberRef(ctx, stable.NewDirectoryAdministrativeUnitID(id.AdministrativeUnitId), addMemberProperties, administrativeunitmember.DefaultAddAdministrativeUnitMemberRefOperationOptions()); err != nil {
return tf.ErrorDiagF(err, "Adding member %q to administrative unit %q", id.MemberId, id.AdministrativeUnitId)
}

Expand All @@ -114,12 +106,10 @@ func administrativeUnitMemberResourceCreate(ctx context.Context, d *pluginsdk.Re
MinTimeout: 1 * time.Second,
ContinuousTargetOccurence: 3,
Refresh: func() (interface{}, string, error) {
_, status, err := client.GetMember(ctx, id.AdministrativeUnitId, id.MemberId)
if err != nil {
if status == http.StatusNotFound {
return "stub", "Waiting", nil
}
if member, err := administrativeUnitGetMember(ctx, memberClient, id.AdministrativeUnitId, id.MemberId); err != nil {
return nil, "Error", fmt.Errorf("retrieving member")
} else if member == nil {
return "stub", "Waiting", nil
}
return "stub", "Done", nil
},
Expand All @@ -134,20 +124,19 @@ func administrativeUnitMemberResourceCreate(ctx context.Context, d *pluginsdk.Re
}

func administrativeUnitMemberResourceRead(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics {
client := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitsClient
memberClient := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitMemberClient

id, err := parse.AdministrativeUnitMemberID(d.Id())
if err != nil {
return tf.ErrorDiagPathF(err, "id", "Parsing Administrative Unit Member ID %q", d.Id())
}

if _, status, err := client.GetMember(ctx, id.AdministrativeUnitId, id.MemberId); err != nil {
if status == http.StatusNotFound {
log.Printf("[DEBUG] Member with ID %q was not found in administrative unit %q - removing from state", id.MemberId, id.AdministrativeUnitId)
d.SetId("")
return nil
}
if member, err := administrativeUnitGetMember(ctx, memberClient, id.AdministrativeUnitId, id.MemberId); err != nil {
return tf.ErrorDiagF(err, "Retrieving member %q for administrative unit with object ID: %q", id.MemberId, id.AdministrativeUnitId)
} else if member == nil {
log.Printf("[DEBUG] Member with ID %q was not found in administrative unit %q - removing from state", id.MemberId, id.AdministrativeUnitId)
d.SetId("")
return nil
}

tf.Set(d, "administrative_unit_object_id", id.AdministrativeUnitId)
Expand All @@ -157,7 +146,7 @@ func administrativeUnitMemberResourceRead(ctx context.Context, d *pluginsdk.Reso
}

func administrativeUnitMemberResourceDelete(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics {
client := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitsClient
memberClient := meta.(*clients.Client).AdministrativeUnits.AdministrativeUnitMemberClient

id, err := parse.AdministrativeUnitMemberID(d.Id())
if err != nil {
Expand All @@ -167,19 +156,16 @@ func administrativeUnitMemberResourceDelete(ctx context.Context, d *pluginsdk.Re
tf.LockByName(administrativeUnitResourceName, id.AdministrativeUnitId)
defer tf.UnlockByName(administrativeUnitResourceName, id.AdministrativeUnitId)

if _, err := client.RemoveMembers(ctx, id.AdministrativeUnitId, &[]string{id.MemberId}); err != nil {
if _, err := memberClient.RemoveAdministrativeUnitMemberRef(ctx, stable.NewDirectoryAdministrativeUnitIdMemberID(id.AdministrativeUnitId, id.MemberId), administrativeunitmember.DefaultRemoveAdministrativeUnitMemberRefOperationOptions()); err != nil {
return tf.ErrorDiagF(err, "Removing member %q from administrative unit with object ID: %q", id.MemberId, id.AdministrativeUnitId)
}

// Wait for membership link to be deleted
if err := helpers.WaitForDeletion(ctx, func(ctx context.Context) (*bool, error) {
defer func() { client.BaseClient.DisableRetries = false }()
client.BaseClient.DisableRetries = true
if _, status, err := client.GetMember(ctx, id.AdministrativeUnitId, id.MemberId); err != nil {
if status == http.StatusNotFound {
return pointer.To(false), nil
}
if err := consistency.WaitForDeletion(ctx, func(ctx context.Context) (*bool, error) {
if member, err := administrativeUnitGetMember(ctx, memberClient, id.AdministrativeUnitId, id.MemberId); err != nil {
return nil, err
} else if member == nil {
return pointer.To(false), nil
}
return pointer.To(true), nil
}); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ package administrativeunits_test
import (
"context"
"fmt"
"net/http"
"testing"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/directory/stable/administrativeunitmember"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-azuread/internal/acceptance"
"github.com/hashicorp/terraform-provider-azuread/internal/acceptance/check"
Expand Down Expand Up @@ -109,23 +111,33 @@ func TestAccAdministrativeUnitMember_requiresImport(t *testing.T) {
}

func (r AdministrativeUnitMemberResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
client := clients.AdministrativeUnits.AdministrativeUnitsClient
client.BaseClient.DisableRetries = true
defer func() { client.BaseClient.DisableRetries = false }()
client := clients.AdministrativeUnits.AdministrativeUnitMemberClient

id, err := parse.AdministrativeUnitMemberID(state.ID)
if err != nil {
return nil, fmt.Errorf("parsing Administrative Unit Member ID: %v", err)
}

if _, status, err := client.GetMember(ctx, id.AdministrativeUnitId, id.MemberId); err != nil {
if status == http.StatusNotFound {
options := administrativeunitmember.ListAdministrativeUnitMembersOperationOptions{
Filter: pointer.To(fmt.Sprintf("id eq '%s'", id.MemberId)),
}
resp, err := client.ListAdministrativeUnitMembers(ctx, stable.NewDirectoryAdministrativeUnitID(id.AdministrativeUnitId), options)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return pointer.To(false), nil
}
return nil, fmt.Errorf("failed to retrieve administrative unit member %q (administrative unit ID: %q): %+v", id.MemberId, id.AdministrativeUnitId, err)
}

return pointer.To(true), nil
if resp.Model != nil {
for _, member := range *resp.Model {
if pointer.From(member.DirectoryObject().Id) == id.MemberId {
return pointer.To(true), nil
}
}
}

return pointer.To(false), nil
}

func (AdministrativeUnitMemberResource) templateThreeUsers(data acceptance.TestData) string {
Expand Down
Loading
Loading