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

bug fix: try SG permission add prior to revoke #3952

Merged
merged 2 commits into from
Dec 17, 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
2 changes: 1 addition & 1 deletion pkg/networking/security_group_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (opts *FetchSGInfoOptions) ApplyOptions(options ...FetchSGInfoOption) {

type FetchSGInfoOption func(opts *FetchSGInfoOptions)

// WithReloadIgnoringCache is a option that sets the ReloadIgnoringCache to true.
// WithReloadIgnoringCache is an option that sets the ReloadIgnoringCache to true.
func WithReloadIgnoringCache() FetchSGInfoOption {
return func(opts *FetchSGInfoOptions) {
opts.ReloadIgnoringCache = true
Expand Down
41 changes: 32 additions & 9 deletions pkg/networking/security_group_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,23 +77,24 @@ func (r *defaultSecurityGroupReconciler) ReconcileIngress(ctx context.Context, s
return err
}
sgInfo := sgInfoByID[sgID]
if err := r.reconcileIngressWithSGInfo(ctx, sgInfo, desiredPermissions, reconcileOpts); err != nil {

if err := r.reconcileIngressWithSGInfo(ctx, sgInfo, desiredPermissions, false, reconcileOpts); err != nil {
if !r.shouldRetryWithoutCache(err) {
return err
}
revokeFirst := r.shouldRemoveSGRulesFirst(err)
r.logger.Info("Retrying ReconcileIngress without using cache", "revokeFirst", revokeFirst)
sgInfoByID, err := r.sgManager.FetchSGInfosByID(ctx, []string{sgID}, WithReloadIgnoringCache())
if err != nil {
return err
}
sgInfo := sgInfoByID[sgID]
if err := r.reconcileIngressWithSGInfo(ctx, sgInfo, desiredPermissions, reconcileOpts); err != nil {
return err
}
return r.reconcileIngressWithSGInfo(ctx, sgInfo, desiredPermissions, revokeFirst, reconcileOpts)
}
return nil
}

func (r *defaultSecurityGroupReconciler) reconcileIngressWithSGInfo(ctx context.Context, sgInfo SecurityGroupInfo, desiredPermissions []IPPermissionInfo, reconcileOpts SecurityGroupReconcileOptions) error {
func (r *defaultSecurityGroupReconciler) reconcileIngressWithSGInfo(ctx context.Context, sgInfo SecurityGroupInfo, desiredPermissions []IPPermissionInfo, revokeFirst bool, reconcileOpts SecurityGroupReconcileOptions) error {
extraPermissions := diffIPPermissionInfos(sgInfo.Ingress, desiredPermissions)
permissionsToRevoke := make([]IPPermissionInfo, 0, len(extraPermissions))
for _, permission := range extraPermissions {
Expand All @@ -102,24 +103,46 @@ func (r *defaultSecurityGroupReconciler) reconcileIngressWithSGInfo(ctx context.
}
}
permissionsToGrant := diffIPPermissionInfos(desiredPermissions, sgInfo.Ingress)
if len(permissionsToRevoke) > 0 && !reconcileOpts.AuthorizeOnly {
if err := r.sgManager.RevokeSGIngress(ctx, sgInfo.SecurityGroupID, permissionsToRevoke); err != nil {
return err

if revokeFirst {
if len(permissionsToRevoke) > 0 && !reconcileOpts.AuthorizeOnly {
if err := r.sgManager.RevokeSGIngress(ctx, sgInfo.SecurityGroupID, permissionsToRevoke); err != nil {
return err
}
}
}

if len(permissionsToGrant) > 0 {
if err := r.sgManager.AuthorizeSGIngress(ctx, sgInfo.SecurityGroupID, permissionsToGrant); err != nil {
return err
}
}

if !revokeFirst {
if len(permissionsToRevoke) > 0 && !reconcileOpts.AuthorizeOnly {
if err := r.sgManager.RevokeSGIngress(ctx, sgInfo.SecurityGroupID, permissionsToRevoke); err != nil {
return err
}
}
}

return nil
}

// shouldRetryWithoutCache tests whether we should retry SecurityGroup rules reconcile without cache.
func (r *defaultSecurityGroupReconciler) shouldRetryWithoutCache(err error) bool {
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return apiErr.ErrorCode() == "InvalidPermission.Duplicate" || apiErr.ErrorCode() == "InvalidPermission.NotFound"
return apiErr.ErrorCode() == "InvalidPermission.Duplicate" || apiErr.ErrorCode() == "InvalidPermission.NotFound" || apiErr.ErrorCode() == "RulesPerSecurityGroupLimitExceeded"
}
return false
}

// shouldRemoveSGRulesFirst tests whether we should retry SecurityGroup rules reconcile but revoking rules prior to adding new rules.
func (r *defaultSecurityGroupReconciler) shouldRemoveSGRulesFirst(err error) bool {
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return apiErr.ErrorCode() == "RulesPerSecurityGroupLimitExceeded"
}
return false
}
Expand Down
Loading
Loading