Skip to content

Commit dea8fbe

Browse files
dulekmandre
authored andcommitted
Make ensureSecurityRule() safely idempotent (kubernetes#2249)
`ensureSecurityRule()` is used to add a rule to an existing security group. At first it was listing all the rules in the SG and then if the requested rule wasn't present it was adding it. This has some risk - the list of SG rules can be modified in-between by some other thread. This commit changes the logic of that function to just try to create the rule. Neutron API will return 409 Conflict if the rule already exists and if it does OCCM will just ignore the error and move on.
1 parent 1aa6e91 commit dea8fbe

File tree

2 files changed

+20
-22
lines changed

2 files changed

+20
-22
lines changed

pkg/openstack/loadbalancer.go

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,23 +2121,6 @@ func (lbaas *LbaasV2) ensureSecurityRule(
21212121
remoteIPPrefix, secGroupID string,
21222122
portRangeMin, portRangeMax int,
21232123
) error {
2124-
sgListopts := rules.ListOpts{
2125-
Direction: string(direction),
2126-
Protocol: string(protocol),
2127-
PortRangeMax: portRangeMin,
2128-
PortRangeMin: portRangeMax,
2129-
RemoteIPPrefix: remoteIPPrefix,
2130-
SecGroupID: secGroupID,
2131-
}
2132-
sgRules, err := getSecurityGroupRules(lbaas.network, sgListopts)
2133-
if err != nil && !cpoerrors.IsNotFound(err) {
2134-
return fmt.Errorf(
2135-
"failed to find security group rules in %s: %v", secGroupID, err)
2136-
}
2137-
if len(sgRules) != 0 {
2138-
return nil
2139-
}
2140-
21412124
sgRuleCreateOpts := rules.CreateOpts{
21422125
Direction: direction,
21432126
Protocol: protocol,
@@ -2149,11 +2132,12 @@ func (lbaas *LbaasV2) ensureSecurityRule(
21492132
}
21502133

21512134
mc := metrics.NewMetricContext("security_group_rule", "create")
2152-
_, err = rules.Create(lbaas.network, sgRuleCreateOpts).Extract()
2153-
if mc.ObserveRequest(err) != nil {
2154-
return fmt.Errorf(
2155-
"failed to create rule for security group %s: %v",
2156-
secGroupID, err)
2135+
_, err := rules.Create(lbaas.network, sgRuleCreateOpts).Extract()
2136+
if err != nil && cpoerrors.IsConflictError(err) {
2137+
// Conflict means the SG rule already exists, so ignoring that error.
2138+
return mc.ObserveRequest(nil)
2139+
} else if mc.ObserveRequest(err) != nil {
2140+
return fmt.Errorf("failed to create rule for security group %s: %v", secGroupID, err)
21572141
}
21582142
return nil
21592143
}

pkg/util/errors/errors.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,17 @@ func IsInvalidError(err error) bool {
7777

7878
return false
7979
}
80+
81+
func IsConflictError(err error) bool {
82+
if _, ok := err.(gophercloud.ErrDefault409); ok {
83+
return true
84+
}
85+
86+
if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok {
87+
if errCode.Actual == http.StatusConflict {
88+
return true
89+
}
90+
}
91+
92+
return false
93+
}

0 commit comments

Comments
 (0)