Repository navigation
fix: make frontend cluster create idempotent to prevent CS duplicate collisions #6025
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -369,26 +369,48 @@ func (f *Frontend) createHCPCluster(writer http.ResponseWriter, request *http.Re | |
| tenantID = *subscription.Properties.TenantId | ||
| } | ||
|
|
||
| initialClusterProperties := map[string]string{} | ||
| if len(f.clusterServiceProvisionShard) != 0 { | ||
| initialClusterProperties[ocm.CSPropertyProvisionShardID] = f.clusterServiceProvisionShard | ||
| } | ||
| if f.clusterServiceNoopProvision { | ||
| initialClusterProperties[ocm.CSPropertyNoopProvision] = ocm.CSPropertyEnabled | ||
| } | ||
| if f.clusterServiceNoopDeprovision { | ||
| initialClusterProperties[ocm.CSPropertyNoopDeprovision] = ocm.CSPropertyEnabled | ||
| } | ||
| newClusterServiceClusterBuilder, newClusterServiceAutoscalerBuilder, err := ocm.BuildCSCluster(newInternalCluster.ID, tenantID, newInternalCluster, initialClusterProperties, nil, nil) | ||
| if err != nil { | ||
| return utils.TrackError(err) | ||
| } | ||
| logger.Info(fmt.Sprintf("creating resource %s", newInternalCluster.ID)) | ||
| resultingClusterServiceCluster, err := f.clusterServiceClient.PostCluster(ctx, newClusterServiceClusterBuilder, newClusterServiceAutoscalerBuilder) | ||
|
|
||
| // Check if CS already has a cluster with matching Azure metadata. This | ||
| // handles the retry-after-partial-failure scenario: a prior attempt may | ||
| // have created the CS cluster but failed to write the Cosmos documents, | ||
| // leaving an orphan in CS that would cause PostCluster to reject with | ||
| // "Duplicate ARO-HCP cluster name" (see ARO-27951). | ||
| resultingClusterServiceCluster, err := ocm.FindClusterByAzureInfo( | ||
| ctx, f.clusterServiceClient, | ||
| newInternalCluster.ID.SubscriptionID, | ||
| newInternalCluster.ID.ResourceGroupName, | ||
| newInternalCluster.Name, | ||
| tenantID, | ||
| newInternalCluster.CustomerProperties.Platform.ManagedResourceGroup, | ||
| ) | ||
| if err != nil { | ||
| return utils.TrackError(err) | ||
| } | ||
|
|
||
| if resultingClusterServiceCluster == nil { | ||
| initialClusterProperties := map[string]string{} | ||
| if len(f.clusterServiceProvisionShard) != 0 { | ||
| initialClusterProperties[ocm.CSPropertyProvisionShardID] = f.clusterServiceProvisionShard | ||
| } | ||
| if f.clusterServiceNoopProvision { | ||
| initialClusterProperties[ocm.CSPropertyNoopProvision] = ocm.CSPropertyEnabled | ||
| } | ||
| if f.clusterServiceNoopDeprovision { | ||
| initialClusterProperties[ocm.CSPropertyNoopDeprovision] = ocm.CSPropertyEnabled | ||
| } | ||
| newClusterServiceClusterBuilder, newClusterServiceAutoscalerBuilder, err := ocm.BuildCSCluster(newInternalCluster.ID, tenantID, newInternalCluster, initialClusterProperties, nil, nil) | ||
| if err != nil { | ||
| return utils.TrackError(err) | ||
| } | ||
| resultingClusterServiceCluster, err = f.clusterServiceClient.PostCluster(ctx, newClusterServiceClusterBuilder, newClusterServiceAutoscalerBuilder) | ||
| if err != nil { | ||
| return utils.TrackError(err) | ||
| } | ||
| } else { | ||
| logger.Info("Reusing existing Cluster Service cluster found by Azure metadata", "csClusterHREF", resultingClusterServiceCluster.HREF()) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need this PR anymore, but I am curious what you think should happen if hte content in the existing cluster-service instance does not match the new create call.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there wasn't a 100% match, it was going to create a new one (not reuse the old one). My understanding was a partial match was not duplicative so a new one could be created without conflict/idempotentcy issues. |
||
| } | ||
|
|
||
| csID, err := api.NewInternalID(resultingClusterServiceCluster.HREF()) | ||
| if err != nil { | ||
| return utils.TrackError(err) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.