iptables: add idempotent functions

Add the following idempotent functions to iptables utils:

DeleteRule: idempotently delete an iptables rule
DeleteChain: idempotently delete an iptables chain
ClearChain: idempotently flush an iptables chain

Signed-off-by: Antonio Ojea <antonio.ojea.garcia@gmail.com>
This commit is contained in:
Antonio Ojea
2019-12-12 14:03:33 +01:00
parent 3603738c6a
commit bf8f171041
3 changed files with 88 additions and 36 deletions

View File

@ -62,3 +62,60 @@ func ChainExists(ipt *iptables.IPTables, table, chain string) (bool, error) {
}
return false, nil
}
// DeleteRule idempotently delete the iptables rule in the specified table/chain.
// It does not return an error if the referring chain doesn't exist
func DeleteRule(ipt *iptables.IPTables, table, chain string, rulespec ...string) error {
if ipt == nil {
return errors.New("failed to ensure iptable chain: IPTables was nil")
}
if err := ipt.Delete(table, chain, rulespec...); err != nil {
eerr, eok := err.(*iptables.Error)
switch {
case eok && eerr.IsNotExist():
// swallow here, the chain was already deleted
return nil
case eok && eerr.ExitStatus() == 2:
// swallow here, invalid command line parameter because the referring rule is missing
return nil
default:
return fmt.Errorf("Failed to delete referring rule %s %s: %v", table, chain, err)
}
}
return nil
}
// DeleteChain idempotently deletes the specified table/chain.
// It does not return an errors if the chain does not exist
func DeleteChain(ipt *iptables.IPTables, table, chain string) error {
if ipt == nil {
return errors.New("failed to ensure iptable chain: IPTables was nil")
}
err := ipt.DeleteChain(table, chain)
eerr, eok := err.(*iptables.Error)
switch {
case eok && eerr.IsNotExist():
// swallow here, the chain was already deleted
return nil
default:
return err
}
}
// ClearChain idempotently clear the iptables rules in the specified table/chain.
// If the chain does not exist, a new one will be created
func ClearChain(ipt *iptables.IPTables, table, chain string) error {
if ipt == nil {
return errors.New("failed to ensure iptable chain: IPTables was nil")
}
err := ipt.ClearChain(table, chain)
eerr, eok := err.(*iptables.Error)
switch {
case eok && eerr.IsNotExist():
// swallow here, the chain was already deleted
return EnsureChain(ipt, table, chain)
default:
return err
}
}