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:
parent
3603738c6a
commit
bf8f171041
@ -62,3 +62,60 @@ func ChainExists(ipt *iptables.IPTables, table, chain string) (bool, error) {
|
|||||||
}
|
}
|
||||||
return false, nil
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -67,12 +67,31 @@ var _ = Describe("chain tests", func() {
|
|||||||
cleanup()
|
cleanup()
|
||||||
})
|
})
|
||||||
|
|
||||||
It("creates chains idempotently", func() {
|
Describe("EnsureChain", func() {
|
||||||
err := EnsureChain(ipt, TABLE, testChain)
|
It("creates chains idempotently", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
err := EnsureChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
// Create it again!
|
// Create it again!
|
||||||
err = EnsureChain(ipt, TABLE, testChain)
|
err = EnsureChain(ipt, TABLE, testChain)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Describe("DeleteChain", func() {
|
||||||
|
It("delete chains idempotently", func() {
|
||||||
|
// Create chain
|
||||||
|
err := EnsureChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Delete chain
|
||||||
|
err = DeleteChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Delete it again!
|
||||||
|
err = DeleteChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -70,15 +70,8 @@ func (c *chain) teardown(ipt *iptables.IPTables) error {
|
|||||||
// flush the chain
|
// flush the chain
|
||||||
// This will succeed *and create the chain* if it does not exist.
|
// This will succeed *and create the chain* if it does not exist.
|
||||||
// If the chain doesn't exist, the next checks will fail.
|
// If the chain doesn't exist, the next checks will fail.
|
||||||
if err := ipt.ClearChain(c.table, c.name); err != nil {
|
if err := utils.ClearChain(ipt, c.table, c.name); err != nil {
|
||||||
eerr, eok := err.(*iptables.Error)
|
return err
|
||||||
switch {
|
|
||||||
case eok && eerr.IsNotExist():
|
|
||||||
// swallow here, the chain was already deleted
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entryChain := range c.entryChains {
|
for _, entryChain := range c.entryChains {
|
||||||
@ -97,32 +90,15 @@ func (c *chain) teardown(ipt *iptables.IPTables) error {
|
|||||||
}
|
}
|
||||||
chainParts = chainParts[2:] // List results always include an -A CHAINNAME
|
chainParts = chainParts[2:] // List results always include an -A CHAINNAME
|
||||||
|
|
||||||
if err := ipt.Delete(c.table, entryChain, chainParts...); err != nil {
|
if err := utils.DeleteRule(ipt, c.table, entryChain, chainParts...); err != nil {
|
||||||
eerr, eok := err.(*iptables.Error)
|
return err
|
||||||
switch {
|
|
||||||
case eok && eerr.IsNotExist():
|
|
||||||
// swallow here, the chain was already deleted
|
|
||||||
continue
|
|
||||||
case eok && eerr.ExitStatus() == 2:
|
|
||||||
// swallow here, invalid command line parameter because the referring rule is missing
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Failed to delete referring rule %s %s: %v", c.table, entryChainRule, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ipt.DeleteChain(c.table, c.name)
|
return utils.DeleteChain(ipt, c.table, c.name)
|
||||||
eerr, eok := err.(*iptables.Error)
|
|
||||||
switch {
|
|
||||||
case eok && eerr.IsNotExist():
|
|
||||||
// swallow here, the chain was already deleted
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertUnique will add a rule to a chain if it does not already exist.
|
// insertUnique will add a rule to a chain if it does not already exist.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user