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

New resources azurerm_capacity_reservation_group and azurerm_capacity_reservation #16464

Merged
merged 6 commits into from Jun 8, 2022

Conversation

myc2h6o
Copy link
Contributor

@myc2h6o myc2h6o commented Apr 20, 2022

@myc2h6o
Copy link
Contributor Author

myc2h6o commented Apr 20, 2022

Test result:
image

Copy link
Member

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

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

hi @myc2h6o

Thanks for opening this PR - I've taken a look through and left some comments inline, if we can fix those up then we should be able to take another look here.

Thanks!

Comment on lines 49 to 58
"resource_group_name": azure.SchemaResourceGroupName(),

"location": azure.SchemaLocation(),

"capacity_reservation_group_name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},
Copy link
Member

Choose a reason for hiding this comment

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

this should be passing the Capacity Reservation Group ID and parsing these values instead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed these three and added capacity_reservation_group_id, including location which must be same with the capacity reservation group.

Comment on lines 115 to 118
if v, ok := d.GetOk("zone"); ok {
zones := []string{v.(string)}
parameters.Zones = &zones
}
Copy link
Member

Choose a reason for hiding this comment

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

this should be using the common Expand/Flatten functions for Zones: https://github.com/hashicorp/go-azure-helpers/blob/main/resourcemanager/zones/expand.go

Copy link
Contributor Author

@myc2h6o myc2h6o Apr 24, 2022

Choose a reason for hiding this comment

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

The API exposes zones, however, it can only accept one zone, so used the non-common way to expand/flatten this. Similar to managed_disk.zone. Updated a little bit in the new commit though to make it more consistent

if zone, ok := d.GetOk("zone"); ok {
createDisk.Zones = &[]string{
zone.(string),
}
}

resp, err := client.Get(ctx, id.ResourceGroup, id.CapacityReservationGroupName, id.Name, "")
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[INFO] Capacity Reservation %q does not exist - removing from state", d.Id())
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
log.Printf("[INFO] Capacity Reservation %q does not exist - removing from state", d.Id())
log.Printf("[INFO] %s was not found - removing from state", *id)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing out, updated

Comment on lines 160 to 162
if zones := resp.Zones; zones != nil && len(*zones) > 0 {
d.Set("zone", (*zones)[0])
}
Copy link
Member

Choose a reason for hiding this comment

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

this should be using the common Expand/Flatten functions for Zones: https://github.com/hashicorp/go-azure-helpers/blob/main/resourcemanager/zones/flatten.go

Copy link
Contributor Author

@myc2h6o myc2h6o Apr 24, 2022

Choose a reason for hiding this comment

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

The API exposes zones, however, it can only accept one zone, so used the non-common way to expand/flatten this. Similar to managed_disk.zone. Updated a little bit in the new commit though to make it more consistent

zone := ""
if resp.Zones != nil && len(*resp.Zones) > 0 {
z := *resp.Zones
zone = z[0]
}
d.Set("zone", zone)

Comment on lines 207 to 217
future, err := client.Delete(ctx, id.ResourceGroup, id.CapacityReservationGroupName, id.Name)
if err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}

if err := future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for deletion of %s: %+v", id, err)
}

// API has bug, which appears to be eventually consistent.
log.Printf("[DEBUG] Waiting for %s to be fully deleted..", *id)
Copy link
Member

Choose a reason for hiding this comment

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

where's the Swagger bug for this? There's no point using the WaitForCompletion if this API is broken

Suggested change
future, err := client.Delete(ctx, id.ResourceGroup, id.CapacityReservationGroupName, id.Name)
if err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}
if err := future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for deletion of %s: %+v", id, err)
}
// API has bug, which appears to be eventually consistent.
log.Printf("[DEBUG] Waiting for %s to be fully deleted..", *id)
if _, err := client.Delete(ctx, id.ResourceGroup, id.CapacityReservationGroupName, id.Name); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}
// API has bug, which appears to be eventually consistent.
log.Printf("[DEBUG] Waiting for %s to be fully deleted..", *id)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have opened an issue within Azure spec repo, updated in code comment as well
Azure/azure-rest-api-specs#18767

"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
Copy link
Member

Choose a reason for hiding this comment

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

we should validate the name

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have added the validation for name

Comment on lines +87 to +90
zones := zones.Expand(d.Get("zones").(*schema.Set).List())
if len(zones) > 0 {
parameters.Zones = &zones
}
Copy link
Member

Choose a reason for hiding this comment

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

this should be using the standard Expand functions for Zones

Copy link
Contributor Author

Choose a reason for hiding this comment

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

different from the other resource in this change, in line 87 (before the new commit), already used the standard zones.Expand

resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "")
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[INFO] Capacity Reservation Group %q does not exist - removing from state", d.Id())
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
log.Printf("[INFO] Capacity Reservation Group %q does not exist - removing from state", d.Id())
log.Printf("[INFO] %s was not found - removing from state", *id)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

Comment on lines 159 to 161
if _, err := client.Delete(ctx, id.ResourceGroup, id.Name); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}
Copy link
Member

Choose a reason for hiding this comment

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

so this is gone straight away? given the other API has issues, are there any API errors when deleting multiple reservations within a parent group here?

Copy link
Contributor Author

@myc2h6o myc2h6o Apr 24, 2022

Choose a reason for hiding this comment

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

This api only has the non-future version: https://github.com/Azure/azure-sdk-for-go/blob/bf144f61fde04d2f29dd52d84f25e931cea67fd8/services/compute/mgmt/2021-11-01/compute/capacityreservationgroups.go#L120.
The api issue is that, although capacity reservation is deleted and not present in the Get response, capacity reservation group still needs some additional wait (about 5 seconds) to realize that, so added the wait in the capacity reservation deletion. Have put the detail in spec repo Azure/azure-rest-api-specs#18767

Copy link
Collaborator

Choose a reason for hiding this comment

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

i don't see any wait? we souldn't be waiting and instead poll to check until its finished

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @katbyte The deletion for this resource capacity_reservation_group is synchrounous per sdk.

And the wait and poll is for the other resource capaicty_reservation below in this change, where the asynchronous sdk has bug

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just took another thought. The actual issue Azure/azure-rest-api-specs#18767 happens within deleting the parent resource capacity_reservation_group due to cache refresh issue. So instead of adding a wait on capacity_reservation, probably it's better to add a retry logic on the parent resource here itself. I'll update the pr and let you know once it's ready to be reviewed again

@myc2h6o
Copy link
Contributor Author

myc2h6o commented Apr 24, 2022

Updated test result
image

@myc2h6o
Copy link
Contributor Author

myc2h6o commented Apr 24, 2022

Hi @tombuildsstuff Thanks for reviewing the pr! I've updated the pr to resolve the comments, please take a look. Thanks!

Comment on lines 159 to 161
if _, err := client.Delete(ctx, id.ResourceGroup, id.Name); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

i don't see any wait? we souldn't be waiting and instead poll to check until its finished

@myc2h6o
Copy link
Contributor Author

myc2h6o commented May 18, 2022

Hi @katbyte I've updated the delete operation of capacity_reservation_resource to use future.WaitForCompletionRef and move the workaround of Azure/azure-rest-api-specs#18767 to capacity_reservation_group_resource, by adding a delete retry after 1 minutes, as the cache of reservation list is refreshed in a few seconds.

@myc2h6o
Copy link
Contributor Author

myc2h6o commented May 18, 2022

Test result:
image

Copy link
Collaborator

@katbyte katbyte left a comment

Choose a reason for hiding this comment

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

Thanks @myc2h6o - LGTM 🌻

// It takes several seconds to sync the cache of reservations list in Capacity Reservation Group. Delete operation requires the list to be empty, and fails before the cache sync is completed.
// Retry the delete operation after a minute as a workaround. Issue is tracked by: https://github.com/Azure/azure-rest-api-specs/issues/18767
if _, err := client.Delete(ctx, id.ResourceGroup, id.Name); err != nil {
time.Sleep(1 * time.Minute)
Copy link
Collaborator

Choose a reason for hiding this comment

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

i just noticed this - we should not be sleeping. is there something you can check/poll on instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@katbyte I tried get the reservations list in the reservation group but unfortunately it changes to empty very soon after the reservation is deleted. However, even if it's empty, the deletion still needs some additional seconds to work

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I saw the deletion in resource_group waits for 30 seconds in each polling, maybe we can wait for 30 seconds instead here as well? The internal cache is invisible from api but it shall be sync in less than 10 seconds

if len(nestedResourceIds) > 0 {
time.Sleep(30 * time.Second)
return pluginsdk.RetryableError(resourceGroupContainsItemsError(id.ResourceGroup, nestedResourceIds))

Copy link
Collaborator

Choose a reason for hiding this comment

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

that is inside a retry function and acts as a delay between checking, it was a quick hack that was put in post 3.0 in 3.0.1 very quickly and should likely be changed/fixed to a state wait.

Could we instead put this inside a statewait where the retry and sleep logic is handled correctly? thanksa

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@katbyte yes it's better to use the common way. I've moved the deletion workaround into a stateRefresh function, can you take a look? Thanks!

@myc2h6o
Copy link
Contributor Author

myc2h6o commented Jun 1, 2022

Updated test result
image

Copy link
Collaborator

@katbyte katbyte left a comment

Choose a reason for hiding this comment

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

Thanks @myc2h6o - LGTM 👍

@katbyte katbyte merged commit 5e1cb6d into hashicorp:main Jun 8, 2022
@katbyte katbyte changed the title New resources capacity_reservation_group and capacity_reservation New resources azurerm_capacity_reservation_group and azurerm_capacity_reservation Jun 8, 2022
@github-actions github-actions bot added this to the v3.10.0 milestone Jun 8, 2022
katbyte added a commit that referenced this pull request Jun 8, 2022
@myc2h6o myc2h6o deleted the capacity_reservation branch June 9, 2022 03:07
@github-actions
Copy link

This functionality has been released in v3.10.0 of the Terraform Provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you!

katbyte pushed a commit that referenced this pull request Jul 6, 2022
…ion_group_id` (#17236)

Cont. of #16464 to support the Capacity Reservation Group on virtual machine. By specifying the Group ID, the virtual machine will be allocated to the specific Group which has reserved certain VM sizes in advance.
@github-actions
Copy link

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants