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

azuread_[group|user]: wait for replication #91

Merged
merged 18 commits into from
Jun 4, 2019
35 changes: 35 additions & 0 deletions azuread/helpers/graph/replication.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package graph

import (
"fmt"
"time"

"github.com/Azure/go-autorest/autorest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/ar"
)

func WaitForReplication(f func() (interface{}, error)) (interface{}, error) {
return (&resource.StateChangeConf{
Pending: []string{"404", "BadCast"},
Target: []string{"Found"},
Timeout: 5 * time.Minute,
MinTimeout: 1 * time.Second,
ContinuousTargetOccurence: 10,
Refresh: func() (interface{}, string, error) {
i, err := f()
if err != nil {
r, ok := i.(autorest.Response)
if !ok {
return i, "BadCast", nil // sometimes the SDK bubbles up an entirely empty object
}
if ar.ResponseWasNotFound(r) {
return i, "404", nil
}
return i, "Error", fmt.Errorf("Error calling f, response was not 404 (%d): %v", r.StatusCode, err)
}

return i, "Found", nil
},
}).WaitForState()
}
18 changes: 7 additions & 11 deletions azuread/resource_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package azuread
import (
"fmt"
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
"github.com/hashicorp/terraform/helper/resource"

"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/ar"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/graph"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/p"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/tf"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate"
Expand Down Expand Up @@ -229,15 +229,11 @@ func resourceApplicationCreate(d *schema.ResourceData, meta interface{}) error {
}
d.SetId(*app.ObjectID)

// mimicking the behaviour of az tool retry until a successful get
if err := resource.Retry(3*time.Minute, func() *resource.RetryError {
if _, err := client.Get(ctx, *app.ObjectID); err != nil {
return resource.RetryableError(err)
}

return nil
}); err != nil {
return fmt.Errorf("Error waiting for Application %q to become available: %+v", name, err)
_, err = graph.WaitForReplication(func() (interface{}, error) {
return client.Get(ctx, *app.ObjectID)
})
if err != nil {
return fmt.Errorf("Error waiting for Application with ObjectId %q: %+v", *app.ObjectID, err)
}

// follow suggested hack for azure-cli
Expand Down
16 changes: 13 additions & 3 deletions azuread/resource_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/ar"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/graph"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/p"
)

Expand All @@ -17,6 +18,7 @@ func resourceGroup() *schema.Resource {
Create: resourceGroupCreate,
Read: resourceGroupRead,
Delete: resourceGroupDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Expand Down Expand Up @@ -47,11 +49,20 @@ func resourceGroupCreate(d *schema.ResourceData, meta interface{}) error {

group, err := client.Create(ctx, properties)
if err != nil {
return err
return fmt.Errorf("Error retrieving Group (%q): %+v", name, err)
}
if group.ObjectID == nil {
return fmt.Errorf("nil Group ID for %q: %+v", name, err)
}

d.SetId(*group.ObjectID)

_, err = graph.WaitForReplication(func() (interface{}, error) {
return client.Get(ctx, *group.ObjectID)
})
if err != nil {
return fmt.Errorf("Error waiting for Group (%s) with ObjectId %q: %+v", name, *group.ObjectID, err)
}

return resourceGroupRead(d, meta)
}

Expand All @@ -71,7 +82,6 @@ func resourceGroupRead(d *schema.ResourceData, meta interface{}) error {
}

d.Set("name", resp.DisplayName)

return nil
}

Expand Down
17 changes: 6 additions & 11 deletions azuread/resource_service_principal.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ package azuread
import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform/helper/resource"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/graph"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/tf"

"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate"
Expand Down Expand Up @@ -80,15 +79,11 @@ func resourceServicePrincipalCreate(d *schema.ResourceData, meta interface{}) er
}
d.SetId(*sp.ObjectID)

// mimicking the behaviour of az tool retry until a successful get
if err := resource.Retry(3*time.Minute, func() *resource.RetryError {
if _, err := client.Get(ctx, *sp.ObjectID); err != nil {
return resource.RetryableError(err)
}

return nil
}); err != nil {
return fmt.Errorf("Error waiting for Service Principal %q to become available: %+v", applicationId, err)
_, err = graph.WaitForReplication(func() (interface{}, error) {
return client.Get(ctx, *sp.ObjectID)
})
if err != nil {
return fmt.Errorf("Error waiting for Service Pricipal with ObjectId %q: %+v", *sp.ObjectID, err)
}

return resourceServicePrincipalRead(d, meta)
Expand Down
28 changes: 14 additions & 14 deletions azuread/resource_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/ar"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/graph"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/p"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate"
)
Expand All @@ -19,6 +20,7 @@ func resourceUser() *schema.Resource {
Read: resourceUserRead,
Update: resourceUserUpdate,
Delete: resourceUserDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Expand Down Expand Up @@ -74,7 +76,7 @@ func resourceUserCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).usersClient
ctx := meta.(*ArmClient).StopContext

userPrincipalName := d.Get("user_principal_name").(string)
upn := d.Get("user_principal_name").(string)
displayName := d.Get("display_name").(string)
mailNickName := d.Get("mail_nickname").(string)
accountEnabled := d.Get("account_enabled").(bool)
Expand All @@ -83,7 +85,7 @@ func resourceUserCreate(d *schema.ResourceData, meta interface{}) error {

//default mail nickname to the first part of the UPN (matches the portal)
if mailNickName == "" {
mailNickName = strings.Split(userPrincipalName, "@")[0]
mailNickName = strings.Split(upn, "@")[0]
}

userCreateParameters := graphrbac.UserCreateParameters{
Expand All @@ -94,25 +96,24 @@ func resourceUserCreate(d *schema.ResourceData, meta interface{}) error {
ForceChangePasswordNextLogin: &forcePasswordChange,
Password: &password,
},
UserPrincipalName: &userPrincipalName,
UserPrincipalName: &upn,
}

user, err := client.Create(ctx, userCreateParameters)
if err != nil {
return fmt.Errorf("Error creating User %q: %+v", userPrincipalName, err)
return fmt.Errorf("Error retrieving User (%q): %+v", upn, err)
}
if user.ObjectID == nil {
return fmt.Errorf("nil User ID for %q: %+v", upn, err)
}
d.SetId(*user.ObjectID)

objectId := user.ObjectID

resp, err := client.Get(ctx, *objectId)
_, err = graph.WaitForReplication(func() (interface{}, error) {
return client.Get(ctx, *user.ObjectID)
})
if err != nil {
return fmt.Errorf("Error retrieving User (%q) with ObjectID %q: %+v", userPrincipalName, *objectId, err)
return fmt.Errorf("Error waiting for User (%s) with ObjectId %q: %+v", upn, *user.ObjectID, err)
}
if resp.ObjectID == nil {
return fmt.Errorf("User objectId is nil")
}

d.SetId(*resp.ObjectID)

return resourceUserRead(d, meta)
}
Expand All @@ -138,7 +139,6 @@ func resourceUserRead(d *schema.ResourceData, meta interface{}) error {
d.Set("mail", user.Mail)
d.Set("mail_nickname", user.MailNickname)
d.Set("account_enabled", user.AccountEnabled)

return nil
}

Expand Down