Hello community, here is the log from the commit of package cni-plugins for openSUSE:Factory checked in at 2020-01-12 23:17:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cni-plugins (Old) and /work/SRC/openSUSE:Factory/.cni-plugins.new.6675 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cni-plugins" Sun Jan 12 23:17:46 2020 rev:9 rq:762245 version:0.8.4 Changes: -------- --- /work/SRC/openSUSE:Factory/cni-plugins/cni-plugins.changes 2019-11-15 22:32:41.144062548 +0100 +++ /work/SRC/openSUSE:Factory/.cni-plugins.new.6675/cni-plugins.changes 2020-01-12 23:18:15.370680145 +0100 @@ -1,0 +2,12 @@ +Thu Jan 9 13:24:41 UTC 2020 - Sascha Grunert <[email protected]> + +- Update to version 0.8.4: + * add support for mips64le + * Add missing cniVersion in README example + * bump go-iptables module to v0.4.5 + * iptables: add idempotent functions + * portmap doesn't fail if chain doesn't exist + * fix portmap port forward flakiness + * Add Bruce Ma and Piotr Skarmuk as owners + +------------------------------------------------------------------- Old: ---- cni-plugins-0.8.3.tar.xz New: ---- cni-plugins-0.8.4.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cni-plugins.spec ++++++ --- /var/tmp/diff_new_pack.tiNr9u/_old 2020-01-12 23:18:16.150680433 +0100 +++ /var/tmp/diff_new_pack.tiNr9u/_new 2020-01-12 23:18:16.150680433 +0100 @@ -1,7 +1,7 @@ # # spec file for package cni-plugins # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -20,12 +20,12 @@ %define cni_doc_dir %{_docdir}/cni-plugins Name: cni-plugins -Version: 0.8.3 +Version: 0.8.4 Release: 0 Summary: Container Network Interface plugins License: Apache-2.0 Group: System/Management -Url: https://github.com/containernetworking/plugins +URL: https://github.com/containernetworking/plugins Source: %{name}-%{version}.tar.xz BuildRequires: go >= 1.11 BuildRequires: golang-packaging ++++++ _service ++++++ --- /var/tmp/diff_new_pack.tiNr9u/_old 2020-01-12 23:18:16.170680440 +0100 +++ /var/tmp/diff_new_pack.tiNr9u/_new 2020-01-12 23:18:16.170680440 +0100 @@ -4,8 +4,8 @@ <param name="scm">git</param> <param name="filename">cni-plugins</param> <param name="exclude">.git</param> - <param name="versionformat">0.8.3</param> - <param name="revision">v0.8.3</param> + <param name="versionformat">0.8.4</param> + <param name="revision">v0.8.4</param> <param name="changesgenerate">enable</param> </service> <service name="recompress" mode="disabled"> ++++++ cni-plugins-0.8.3.tar.xz -> cni-plugins-0.8.4.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/.travis.yml new/cni-plugins-0.8.4/.travis.yml --- old/cni-plugins-0.8.3/.travis.yml 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/.travis.yml 2020-01-08 17:26:13.000000000 +0100 @@ -18,6 +18,7 @@ - TARGET=arm64 - TARGET=ppc64le - TARGET=s390x + - TARGET=mips64le matrix: fast_finish: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/OWNERS.md new/cni-plugins-0.8.4/OWNERS.md --- old/cni-plugins-0.8.3/OWNERS.md 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/OWNERS.md 2020-01-08 17:26:13.000000000 +0100 @@ -1,8 +1,10 @@ # Owners This is the official list of the CNI network plugins owners: +- Bruce Ma <[email protected]> (@mars1024) - Bryan Boreham <[email protected]> (@bboreham) - Casey Callendrello <[email protected]> (@squeed) - Dan Williams <[email protected]> (@dcbw) - Gabe Rosenhouse <[email protected]> (@rosenhouse) - Matt Dupre <[email protected]> (@matthewdupre) +- Piotr Skarmuk <[email protected]> (@jellonek) - Stefan Junker <[email protected]> (@steveeJ) \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/go.mod new/cni-plugins-0.8.4/go.mod --- old/cni-plugins-0.8.3/go.mod 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/go.mod 2020-01-08 17:26:13.000000000 +0100 @@ -8,7 +8,7 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 github.com/containernetworking/cni v0.7.1 - github.com/coreos/go-iptables v0.4.2 + github.com/coreos/go-iptables v0.4.5 github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c github.com/d2g/dhcp4client v1.0.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/go.sum new/cni-plugins-0.8.4/go.sum --- old/cni-plugins-0.8.3/go.sum 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/go.sum 2020-01-08 17:26:13.000000000 +0100 @@ -10,6 +10,10 @@ github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/coreos/go-iptables v0.4.2 h1:KH0EwId05JwWIfb96gWvkiT2cbuOu8ygqUaB+yPAwIg= github.com/coreos/go-iptables v0.4.2/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.4.4 h1:5oOUvU7Fk53Hn/rkdJ0zcYGCffotqXpyi4ADCkO1TJ8= +github.com/coreos/go-iptables v0.4.4/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c h1:Xo2rK1pzOm0jO6abTPIQwbAmqBIOj132otexc1mmzFc= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/pkg/utils/iptables.go new/cni-plugins-0.8.4/pkg/utils/iptables.go --- old/cni-plugins-0.8.3/pkg/utils/iptables.go 1970-01-01 01:00:00.000000000 +0100 +++ new/cni-plugins-0.8.4/pkg/utils/iptables.go 2020-01-08 17:26:13.000000000 +0100 @@ -0,0 +1,121 @@ +// Copyright 2017 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "errors" + "fmt" + + "github.com/coreos/go-iptables/iptables" +) + +const statusChainExists = 1 + +// EnsureChain idempotently creates the iptables chain. It does not +// return an error if the chain already exists. +func EnsureChain(ipt *iptables.IPTables, table, chain string) error { + if ipt == nil { + return errors.New("failed to ensure iptable chain: IPTables was nil") + } + exists, err := ChainExists(ipt, table, chain) + if err != nil { + return fmt.Errorf("failed to list iptables chains: %v", err) + } + if !exists { + err = ipt.NewChain(table, chain) + if err != nil { + eerr, eok := err.(*iptables.Error) + if eok && eerr.ExitStatus() != statusChainExists { + return err + } + } + } + return nil +} + +// ChainExists checks whether an iptables chain exists. +func ChainExists(ipt *iptables.IPTables, table, chain string) (bool, error) { + if ipt == nil { + return false, errors.New("failed to check iptable chain: IPTables was nil") + } + chains, err := ipt.ListChains(table) + if err != nil { + return false, err + } + + for _, ch := range chains { + if ch == chain { + return true, 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 + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/pkg/utils/iptables_test.go new/cni-plugins-0.8.4/pkg/utils/iptables_test.go --- old/cni-plugins-0.8.3/pkg/utils/iptables_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/cni-plugins-0.8.4/pkg/utils/iptables_test.go 2020-01-08 17:26:13.000000000 +0100 @@ -0,0 +1,97 @@ +// Copyright 2017-2018 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "fmt" + "math/rand" + "runtime" + + "github.com/containernetworking/plugins/pkg/ns" + "github.com/containernetworking/plugins/pkg/testutils" + "github.com/coreos/go-iptables/iptables" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +const TABLE = "filter" // We'll monkey around here + +var _ = Describe("chain tests", func() { + var testChain string + var ipt *iptables.IPTables + var cleanup func() + + BeforeEach(func() { + + // Save a reference to the original namespace, + // Add a new NS + currNs, err := ns.GetCurrentNS() + Expect(err).NotTo(HaveOccurred()) + + testNs, err := testutils.NewNS() + Expect(err).NotTo(HaveOccurred()) + + testChain = fmt.Sprintf("cni-test-%d", rand.Intn(10000000)) + + ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv4) + Expect(err).NotTo(HaveOccurred()) + + runtime.LockOSThread() + err = testNs.Set() + Expect(err).NotTo(HaveOccurred()) + + cleanup = func() { + if ipt == nil { + return + } + ipt.ClearChain(TABLE, testChain) + ipt.DeleteChain(TABLE, testChain) + currNs.Set() + } + + }) + + AfterEach(func() { + cleanup() + }) + + Describe("EnsureChain", func() { + It("creates chains idempotently", func() { + err := EnsureChain(ipt, TABLE, testChain) + Expect(err).NotTo(HaveOccurred()) + + // Create it again! + err = EnsureChain(ipt, TABLE, testChain) + 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()) + }) + }) + +}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/plugins/main/bridge/README.md new/cni-plugins-0.8.4/plugins/main/bridge/README.md --- old/cni-plugins-0.8.3/plugins/main/bridge/README.md 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/plugins/main/bridge/README.md 2020-01-08 17:26:13.000000000 +0100 @@ -14,17 +14,18 @@ ## Example configuration ``` { - "name": "mynet", - "type": "bridge", - "bridge": "mynet0", - "isDefaultGateway": true, - "forceAddress": false, - "ipMasq": true, - "hairpinMode": true, - "ipam": { - "type": "host-local", - "subnet": "10.10.0.0/16" - } + "cniVersion": "0.3.1", + "name": "mynet", + "type": "bridge", + "bridge": "mynet0", + "isDefaultGateway": true, + "forceAddress": false, + "ipMasq": true, + "hairpinMode": true, + "ipam": { + "type": "host-local", + "subnet": "10.10.0.0/16" + } } ``` @@ -32,10 +33,10 @@ ``` { "cniVersion": "0.3.1", - "name": "mynet", - "type": "bridge", - "bridge": "mynet0", - "ipam": {} + "name": "mynet", + "type": "bridge", + "bridge": "mynet0", + "ipam": {} } ``` @@ -56,4 +57,4 @@ *Note:* The VLAN parameter configures the VLAN tag on the host end of the veth and also enables the vlan_filtering feature on the bridge interface. -*Note:* To configure uplink for L2 network you need to allow the vlan on the uplink interface by using the following command ``` bridge vlan add vid VLAN_ID dev DEV```. \ No newline at end of file +*Note:* To configure uplink for L2 network you need to allow the vlan on the uplink interface by using the following command ``` bridge vlan add vid VLAN_ID dev DEV```. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/plugins/meta/firewall/firewall_iptables_test.go new/cni-plugins-0.8.4/plugins/meta/firewall/firewall_iptables_test.go --- old/cni-plugins-0.8.3/plugins/meta/firewall/firewall_iptables_test.go 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/plugins/meta/firewall/firewall_iptables_test.go 2020-01-08 17:26:13.000000000 +0100 @@ -270,6 +270,13 @@ Expect(err).NotTo(HaveOccurred()) validateFullRuleset(fullConf) + + // ensure creation is idempotent + _, _, err = testutils.CmdAdd(targetNS.Path(), args.ContainerID, IFNAME, fullConf, func() error { + return cmdAdd(args) + }) + Expect(err).NotTo(HaveOccurred()) + return nil }) Expect(err).NotTo(HaveOccurred()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/plugins/meta/firewall/iptables.go new/cni-plugins-0.8.4/plugins/meta/firewall/iptables.go --- old/cni-plugins-0.8.3/plugins/meta/firewall/iptables.go 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/plugins/meta/firewall/iptables.go 2020-01-08 17:26:13.000000000 +0100 @@ -22,6 +22,7 @@ "net" "github.com/containernetworking/cni/pkg/types/current" + "github.com/containernetworking/plugins/pkg/utils" "github.com/coreos/go-iptables/iptables" ) @@ -32,20 +33,6 @@ return rules } -func ensureChain(ipt *iptables.IPTables, table, chain string) error { - chains, err := ipt.ListChains(table) - if err != nil { - return fmt.Errorf("failed to list iptables chains: %v", err) - } - for _, ch := range chains { - if ch == chain { - return nil - } - } - - return ipt.NewChain(table, chain) -} - func generateFilterRule(privChainName string) []string { return []string{"-m", "comment", "--comment", "CNI firewall plugin rules", "-j", privChainName} } @@ -73,10 +60,10 @@ adminRule := generateFilterRule(ib.adminChainName) // Ensure our private chains exist - if err := ensureChain(ipt, "filter", ib.privChainName); err != nil { + if err := utils.EnsureChain(ipt, "filter", ib.privChainName); err != nil { return err } - if err := ensureChain(ipt, "filter", ib.adminChainName); err != nil { + if err := utils.EnsureChain(ipt, "filter", ib.adminChainName); err != nil { return err } @@ -160,10 +147,10 @@ } // Ensure our private chains exist - if err := ensureChain(ipt, "filter", ib.privChainName); err != nil { + if err := utils.EnsureChain(ipt, "filter", ib.privChainName); err != nil { return err } - if err := ensureChain(ipt, "filter", ib.adminChainName); err != nil { + if err := utils.EnsureChain(ipt, "filter", ib.adminChainName); err != nil { return err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/plugins/meta/portmap/chain.go new/cni-plugins-0.8.4/plugins/meta/portmap/chain.go --- old/cni-plugins-0.8.3/plugins/meta/portmap/chain.go 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/plugins/meta/portmap/chain.go 2020-01-08 17:26:13.000000000 +0100 @@ -18,6 +18,7 @@ "fmt" "strings" + "github.com/containernetworking/plugins/pkg/utils" "github.com/coreos/go-iptables/iptables" "github.com/mattn/go-shellwords" ) @@ -35,16 +36,11 @@ // setup idempotently creates the chain. It will not error if the chain exists. func (c *chain) setup(ipt *iptables.IPTables) error { - // create the chain - exists, err := chainExists(ipt, c.table, c.name) + + err := utils.EnsureChain(ipt, c.table, c.name) if err != nil { return err } - if !exists { - if err := ipt.NewChain(c.table, c.name); err != nil { - return err - } - } // Add the rules to the chain for _, rule := range c.rules { @@ -74,7 +70,7 @@ // flush the chain // This will succeed *and create the chain* if it does not exist. // 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 { return err } @@ -94,17 +90,15 @@ } chainParts = chainParts[2:] // List results always include an -A CHAINNAME - if err := ipt.Delete(c.table, entryChain, chainParts...); err != nil { - return fmt.Errorf("Failed to delete referring rule %s %s: %v", c.table, entryChainRule, err) + if err := utils.DeleteRule(ipt, c.table, entryChain, chainParts...); err != nil { + return err } + } } } - if err := ipt.DeleteChain(c.table, c.name); err != nil { - return err - } - return nil + return utils.DeleteChain(ipt, c.table, c.name) } // insertUnique will add a rule to a chain if it does not already exist. @@ -125,24 +119,10 @@ } } -func chainExists(ipt *iptables.IPTables, tableName, chainName string) (bool, error) { - chains, err := ipt.ListChains(tableName) - if err != nil { - return false, err - } - - for _, ch := range chains { - if ch == chainName { - return true, nil - } - } - return false, nil -} - // check the chain. func (c *chain) check(ipt *iptables.IPTables) error { - exists, err := chainExists(ipt, c.table, c.name) + exists, err := utils.ChainExists(ipt, c.table, c.name) if err != nil { return err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/plugins/meta/portmap/chain_test.go new/cni-plugins-0.8.4/plugins/meta/portmap/chain_test.go --- old/cni-plugins-0.8.3/plugins/meta/portmap/chain_test.go 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/plugins/meta/portmap/chain_test.go 2020-01-08 17:26:13.000000000 +0100 @@ -18,6 +18,7 @@ "fmt" "math/rand" "runtime" + "sync" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" @@ -32,6 +33,7 @@ var _ = Describe("chain tests", func() { var testChain chain var ipt *iptables.IPTables + var testNs ns.NetNS var cleanup func() BeforeEach(func() { @@ -41,7 +43,7 @@ currNs, err := ns.GetCurrentNS() Expect(err).NotTo(HaveOccurred()) - testNs, err := testutils.NewNS() + testNs, err = testutils.NewNS() Expect(err).NotTo(HaveOccurred()) tlChainName := fmt.Sprintf("cni-test-%d", rand.Intn(10000000)) @@ -195,4 +197,38 @@ } } }) + + It("deletes chains idempotently in parallel", func() { + defer cleanup() + // number of parallel executions + N := 10 + var wg sync.WaitGroup + err := testChain.setup(ipt) + Expect(err).NotTo(HaveOccurred()) + errCh := make(chan error, N) + for i := 0; i < N; i++ { + wg.Add(1) + go func() { + defer wg.Done() + // teardown chain + errCh <- testNs.Do(func(ns.NetNS) error { + return testChain.teardown(ipt) + }) + }() + } + wg.Wait() + close(errCh) + for err := range errCh { + Expect(err).NotTo(HaveOccurred()) + } + + chains, err := ipt.ListChains(TABLE) + Expect(err).NotTo(HaveOccurred()) + for _, chain := range chains { + if chain == testChain.name { + Fail("Chain was not deleted") + } + } + + }) }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/plugins/meta/portmap/portmap.go new/cni-plugins-0.8.4/plugins/meta/portmap/portmap.go --- old/cni-plugins-0.8.3/plugins/meta/portmap/portmap.go 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/plugins/meta/portmap/portmap.go 2020-01-08 17:26:13.000000000 +0100 @@ -124,7 +124,7 @@ } if ip4t != nil { - exists, err := chainExists(ip4t, dnatChain.table, dnatChain.name) + exists, err := utils.ChainExists(ip4t, dnatChain.table, dnatChain.name) if err != nil { return err } @@ -137,7 +137,7 @@ } if ip6t != nil { - exists, err := chainExists(ip6t, dnatChain.table, dnatChain.name) + exists, err := utils.ChainExists(ip6t, dnatChain.table, dnatChain.name) if err != nil { return err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/plugins/meta/portmap/portmap_integ_test.go new/cni-plugins-0.8.4/plugins/meta/portmap/portmap_integ_test.go --- old/cni-plugins-0.8.3/plugins/meta/portmap/portmap_integ_test.go 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/plugins/meta/portmap/portmap_integ_test.go 2020-01-08 17:26:13.000000000 +0100 @@ -96,119 +96,133 @@ } }) - // This needs to be done using Ginkgo's asynchronous testing mode. - It("forwards a TCP port on ipv4", func(done Done) { - var err error - hostPort := rand.Intn(10000) + 1025 - runtimeConfig := libcni.RuntimeConf{ - ContainerID: fmt.Sprintf("unit-test-%d", hostPort), - NetNS: targetNS.Path(), - IfName: "eth0", - CapabilityArgs: map[string]interface{}{ - "portMappings": []map[string]interface{}{ - { - "hostPort": hostPort, - "containerPort": containerPort, - "protocol": "tcp", + Describe("Creating an interface in a namespace with the ptp plugin", func() { + // This needs to be done using Ginkgo's asynchronous testing mode. + It("forwards a TCP port on ipv4", func(done Done) { + var err error + hostPort := rand.Intn(10000) + 1025 + runtimeConfig := libcni.RuntimeConf{ + ContainerID: fmt.Sprintf("unit-test-%d", hostPort), + NetNS: targetNS.Path(), + IfName: "eth0", + CapabilityArgs: map[string]interface{}{ + "portMappings": []map[string]interface{}{ + { + "hostPort": hostPort, + "containerPort": containerPort, + "protocol": "tcp", + }, }, }, - }, - } + } - // Make delete idempotent, so we can clean up on failure - netDeleted := false - deleteNetwork := func() error { - if netDeleted { - return nil + // Make delete idempotent, so we can clean up on failure + netDeleted := false + deleteNetwork := func() error { + if netDeleted { + return nil + } + netDeleted = true + return cniConf.DelNetworkList(context.TODO(), configList, &runtimeConfig) } - netDeleted = true - return cniConf.DelNetworkList(context.TODO(), configList, &runtimeConfig) - } - // we'll also manually check the iptables chains - ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4) - Expect(err).NotTo(HaveOccurred()) - dnatChainName := genDnatChain("cni-portmap-unit-test", runtimeConfig.ContainerID).name - - // Create the network - resI, err := cniConf.AddNetworkList(context.TODO(), configList, &runtimeConfig) - Expect(err).NotTo(HaveOccurred()) - defer deleteNetwork() - - // Undo Docker's forwarding policy - cmd := exec.Command("iptables", "-t", "filter", - "-P", "FORWARD", "ACCEPT") - cmd.Stderr = GinkgoWriter - err = cmd.Run() - Expect(err).NotTo(HaveOccurred()) - - // Check the chain exists - _, err = ipt.List("nat", dnatChainName) - Expect(err).NotTo(HaveOccurred()) - - result, err := current.GetResult(resI) - Expect(err).NotTo(HaveOccurred()) - var contIP net.IP - - for _, ip := range result.IPs { - intfIndex := *ip.Interface - if result.Interfaces[intfIndex].Sandbox == "" { - continue + // we'll also manually check the iptables chains + ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4) + Expect(err).NotTo(HaveOccurred()) + dnatChainName := genDnatChain("cni-portmap-unit-test", runtimeConfig.ContainerID).name + + // Create the network + resI, err := cniConf.AddNetworkList(context.TODO(), configList, &runtimeConfig) + Expect(err).NotTo(HaveOccurred()) + defer deleteNetwork() + + // Undo Docker's forwarding policy + cmd := exec.Command("iptables", "-t", "filter", + "-P", "FORWARD", "ACCEPT") + cmd.Stderr = GinkgoWriter + err = cmd.Run() + Expect(err).NotTo(HaveOccurred()) + + // Check the chain exists + _, err = ipt.List("nat", dnatChainName) + Expect(err).NotTo(HaveOccurred()) + + result, err := current.GetResult(resI) + Expect(err).NotTo(HaveOccurred()) + var contIP net.IP + + for _, ip := range result.IPs { + intfIndex := *ip.Interface + if result.Interfaces[intfIndex].Sandbox == "" { + continue + } + contIP = ip.Address.IP + } + if contIP == nil { + Fail("could not determine container IP") } - contIP = ip.Address.IP - } - if contIP == nil { - Fail("could not determine container IP") - } - hostIP := getLocalIP() - fmt.Fprintf(GinkgoWriter, "hostIP: %s:%d, contIP: %s:%d\n", - hostIP, hostPort, contIP, containerPort) - - // dump iptables-save output for debugging - cmd = exec.Command("iptables-save") - cmd.Stderr = GinkgoWriter - cmd.Stdout = GinkgoWriter - Expect(cmd.Run()).To(Succeed()) - - // Sanity check: verify that the container is reachable directly - contOK := testEchoServer(contIP.String(), containerPort, "") - - // Verify that a connection to the forwarded port works - dnatOK := testEchoServer(hostIP, hostPort, "") - - // Verify that a connection to localhost works - snatOK := testEchoServer("127.0.0.1", hostPort, "") - - // verify that hairpin works - hairpinOK := testEchoServer(hostIP, hostPort, targetNS.Path()) - - // Cleanup - session.Terminate() - err = deleteNetwork() - Expect(err).NotTo(HaveOccurred()) - - // Verify iptables rules are gone - _, err = ipt.List("nat", dnatChainName) - Expect(err).To(MatchError(ContainSubstring("iptables: No chain/target/match by that name."))) - - // Check that everything succeeded *after* we clean up the network - if !contOK { - Fail("connection direct to " + contIP.String() + " failed") - } - if !dnatOK { - Fail("Connection to " + hostIP + " was not forwarded") - } - if !snatOK { - Fail("connection to 127.0.0.1 was not forwarded") - } - if !hairpinOK { - Fail("Hairpin connection failed") - } + hostIP := getLocalIP() + fmt.Fprintf(GinkgoWriter, "hostIP: %s:%d, contIP: %s:%d\n", + hostIP, hostPort, contIP, containerPort) + + // dump iptables-save output for debugging + cmd = exec.Command("iptables-save") + cmd.Stderr = GinkgoWriter + cmd.Stdout = GinkgoWriter + Expect(cmd.Run()).To(Succeed()) + + // dump ip routes output for debugging + cmd = exec.Command("ip", "route") + cmd.Stderr = GinkgoWriter + cmd.Stdout = GinkgoWriter + Expect(cmd.Run()).To(Succeed()) + + // dump ip addresses output for debugging + cmd = exec.Command("ip", "addr") + cmd.Stderr = GinkgoWriter + cmd.Stdout = GinkgoWriter + Expect(cmd.Run()).To(Succeed()) + + // Sanity check: verify that the container is reachable directly + contOK := testEchoServer(contIP.String(), containerPort, "") + + // Verify that a connection to the forwarded port works + dnatOK := testEchoServer(hostIP, hostPort, "") + + // Verify that a connection to localhost works + snatOK := testEchoServer("127.0.0.1", hostPort, "") + + // verify that hairpin works + hairpinOK := testEchoServer(hostIP, hostPort, targetNS.Path()) + + // Cleanup + session.Terminate() + err = deleteNetwork() + Expect(err).NotTo(HaveOccurred()) + + // Verify iptables rules are gone + _, err = ipt.List("nat", dnatChainName) + Expect(err).To(MatchError(ContainSubstring("iptables: No chain/target/match by that name."))) + + // Check that everything succeeded *after* we clean up the network + if !contOK { + Fail("connection direct to " + contIP.String() + " failed") + } + if !dnatOK { + Fail("Connection to " + hostIP + " was not forwarded") + } + if !snatOK { + Fail("connection to 127.0.0.1 was not forwarded") + } + if !hairpinOK { + Fail("Hairpin connection failed") + } - close(done) + close(done) - }, TIMEOUT*9) + }, TIMEOUT*9) + }) }) // testEchoServer returns true if we found an echo server on the port diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/scripts/release.sh new/cni-plugins-0.8.4/scripts/release.sh --- old/cni-plugins-0.8.3/scripts/release.sh 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/scripts/release.sh 2020-01-08 17:26:13.000000000 +0100 @@ -21,7 +21,7 @@ apk --no-cache add bash tar; cd /go/src/github.com/containernetworking/plugins; umask 0022; - for arch in amd64 arm arm64 ppc64le s390x; do \ + for arch in amd64 arm arm64 ppc64le s390x mips64le; do \ rm -f ${OUTPUT_DIR}/*; \ CGO_ENABLED=0 GOARCH=\$arch ./build_linux.sh ${BUILDFLAGS}; \ for format in tgz; do \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/vendor/github.com/coreos/go-iptables/iptables/iptables.go new/cni-plugins-0.8.4/vendor/github.com/coreos/go-iptables/iptables/iptables.go --- old/cni-plugins-0.8.3/vendor/github.com/coreos/go-iptables/iptables/iptables.go 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/vendor/github.com/coreos/go-iptables/iptables/iptables.go 2020-01-08 17:26:13.000000000 +0100 @@ -48,9 +48,13 @@ // IsNotExist returns true if the error is due to the chain or rule not existing func (e *Error) IsNotExist() bool { - return e.ExitStatus() == 1 && - (e.msg == fmt.Sprintf("%s: Bad rule (does a matching rule exist in that chain?).\n", getIptablesCommand(e.proto)) || - e.msg == fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(e.proto))) + if e.ExitStatus() != 1 { + return false + } + cmdIptables := getIptablesCommand(e.proto) + msgNoRuleExist := fmt.Sprintf("%s: Bad rule (does a matching rule exist in that chain?).\n", cmdIptables) + msgNoChainExist := fmt.Sprintf("%s: No chain/target/match by that name.\n", cmdIptables) + return strings.Contains(e.msg, msgNoRuleExist) || strings.Contains(e.msg, msgNoChainExist) } // Protocol to differentiate between IPv4 and IPv6 @@ -101,7 +105,13 @@ return nil, err } vstring, err := getIptablesVersionString(path) + if err != nil { + return nil, fmt.Errorf("could not get iptables version: %v", err) + } v1, v2, v3, mode, err := extractIptablesVersion(vstring) + if err != nil { + return nil, fmt.Errorf("failed to extract iptables version from [%s]: %v", vstring, err) + } checkPresent, waitPresent, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3) @@ -348,18 +358,6 @@ rules = rules[:len(rules)-1] } - // nftables mode doesn't return an error code when listing a non-existent - // chain. Patch that up. - if len(rules) == 0 && ipt.mode == "nf_tables" { - v := 1 - return nil, &Error{ - cmd: exec.Cmd{Args: args}, - msg: fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(ipt.proto)), - proto: ipt.proto, - exitStatus: &v, - } - } - for i, rule := range rules { rules[i] = filterRuleOutput(rule) } @@ -437,6 +435,7 @@ } ul, err := fmu.tryLock() if err != nil { + syscall.Close(fmu.fd) return err } defer ul.Unlock() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-plugins-0.8.3/vendor/modules.txt new/cni-plugins-0.8.4/vendor/modules.txt --- old/cni-plugins-0.8.3/vendor/modules.txt 2019-11-11 14:07:52.000000000 +0100 +++ new/cni-plugins-0.8.4/vendor/modules.txt 2020-01-08 17:26:13.000000000 +0100 @@ -32,7 +32,7 @@ github.com/containernetworking/cni/pkg/version github.com/containernetworking/cni/pkg/types/020 github.com/containernetworking/cni/libcni -# github.com/coreos/go-iptables v0.4.2 +# github.com/coreos/go-iptables v0.4.5 github.com/coreos/go-iptables/iptables # github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 github.com/coreos/go-systemd/activation
