From fec2d62676cbe4f2fd587b4840c7fc021bead3f9 Mon Sep 17 00:00:00 2001 From: Lionel Jouin Date: Mon, 30 Sep 2024 17:18:23 +0200 Subject: [PATCH] Pass status along ipam update Signed-off-by: Lionel Jouin --- pkg/ipam/ipam.go | 4 +++ pkg/ipam/ipam_linux.go | 8 +++++ pkg/testutils/cmd.go | 9 +++++ pkg/testutils/testing.go | 9 ++++- plugins/main/bridge/bridge.go | 23 ++++++++++--- plugins/main/bridge/bridge_test.go | 13 ++++++++ plugins/main/dummy/dummy.go | 21 +++++++++--- plugins/main/dummy/dummy_test.go | 9 ++++- plugins/main/host-device/host-device.go | 25 +++++++++++--- plugins/main/host-device/host-device_test.go | 11 ++++++- plugins/main/ipvlan/ipvlan.go | 24 +++++++++++--- plugins/main/ipvlan/ipvlan_test.go | 9 ++++- plugins/main/macvlan/macvlan.go | 25 +++++++++++--- plugins/main/macvlan/macvlan_test.go | 30 ++++++++++++++++- plugins/main/ptp/ptp.go | 21 +++++++++--- plugins/main/ptp/ptp_test.go | 10 +++++- plugins/main/tap/tap.go | 23 ++++++++++--- plugins/main/tap/tap_test.go | 16 ++++++++- plugins/main/vlan/vlan.go | 23 ++++++++++--- plugins/main/vlan/vlan_test.go | 9 ++++- .../windows/win-bridge/win-bridge_windows.go | 23 ++++++++++--- .../win-overlay/win-overlay_windows.go | 24 ++++++++++---- plugins/sample/main.go | 33 ++++++++++++++++--- 23 files changed, 348 insertions(+), 54 deletions(-) diff --git a/pkg/ipam/ipam.go b/pkg/ipam/ipam.go index e39d36b08..f6139f7b6 100644 --- a/pkg/ipam/ipam.go +++ b/pkg/ipam/ipam.go @@ -32,3 +32,7 @@ func ExecCheck(plugin string, netconf []byte) error { func ExecDel(plugin string, netconf []byte) error { return invoke.DelegateDel(context.TODO(), plugin, netconf, nil) } + +func ExecStatus(plugin string, netconf []byte) error { + return invoke.DelegateStatus(context.TODO(), plugin, netconf, nil) +} diff --git a/pkg/ipam/ipam_linux.go b/pkg/ipam/ipam_linux.go index 55b67e379..61c673a7c 100644 --- a/pkg/ipam/ipam_linux.go +++ b/pkg/ipam/ipam_linux.go @@ -128,6 +128,14 @@ func ConfigureIface(ifName string, res *current.Result) error { route.Scope = netlink.Scope(*r.Scope) } + if r.Table != nil { + route.Table = *r.Table + } + + if r.Scope != nil { + route.Scope = netlink.Scope(*r.Scope) + } + if err = netlink.RouteAddEcmp(&route); err != nil { return fmt.Errorf("failed to add route '%v via %v dev %v metric %d (Scope: %v, Table: %d)': %v", r.Dst, gw, ifName, r.Priority, route.Scope, route.Table, err) } diff --git a/pkg/testutils/cmd.go b/pkg/testutils/cmd.go index 6f65d6ddd..276f9e5a6 100644 --- a/pkg/testutils/cmd.go +++ b/pkg/testutils/cmd.go @@ -114,3 +114,12 @@ func CmdDel(cniNetns, cniContainerID, cniIfname string, f func() error) error { func CmdDelWithArgs(args *skel.CmdArgs, f func() error) error { return CmdDel(args.Netns, args.ContainerID, args.IfName, f) } + +func CmdStatus(f func() error) error { + os.Setenv("CNI_COMMAND", "STATUS") + os.Setenv("CNI_PATH", os.Getenv("PATH")) + os.Setenv("CNI_NETNS_OVERRIDE", "1") + defer envCleanup() + + return f() +} diff --git a/pkg/testutils/testing.go b/pkg/testutils/testing.go index 9444a8b2d..9f5140fc6 100644 --- a/pkg/testutils/testing.go +++ b/pkg/testutils/testing.go @@ -19,7 +19,7 @@ import ( ) // AllSpecVersions contains all CNI spec version numbers -var AllSpecVersions = [...]string{"0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0"} +var AllSpecVersions = [...]string{"0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0", "1.1.0"} // SpecVersionHasIPVersion returns true if the given CNI specification version // includes the "version" field in the IP address elements @@ -39,6 +39,13 @@ func SpecVersionHasCHECK(ver string) bool { return ok } +// SpecVersionHasSTATUS returns true if the given CNI specification version +// supports the STATUS command +func SpecVersionHasSTATUS(ver string) bool { + ok, _ := version.GreaterThanOrEqualTo(ver, "1.1.0") + return ok +} + // SpecVersionHasChaining returns true if the given CNI specification version // supports plugin chaining func SpecVersionHasChaining(ver string) bool { diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index e878b0a11..78df4c716 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -819,11 +819,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("bridge")) } @@ -1085,3 +1085,18 @@ func cmdCheck(args *skel.CmdArgs) error { func uniqueID(containerID, cniIface string) string { return containerID + "-" + cniIface } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if conf.IPAM.Type != "" { + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + } + + return nil +} diff --git a/plugins/main/bridge/bridge_test.go b/plugins/main/bridge/bridge_test.go index d7d1bd1f0..a1e133139 100644 --- a/plugins/main/bridge/bridge_test.go +++ b/plugins/main/bridge/bridge_test.go @@ -508,6 +508,11 @@ type ( func newTesterByVersion(version string, testNS, targetNS ns.NetNS) cmdAddDelTester { switch { + case strings.HasPrefix(version, "1.1."): + return &testerV10x{ + testNS: testNS, + targetNS: targetNS, + } case strings.HasPrefix(version, "1.0."): return &testerV10x{ testNS: testNS, @@ -1483,6 +1488,14 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re err := tester.testNS.Do(func(ns.NetNS) error { defer GinkgoRecover() + // check that STATUS is + if testutils.SpecVersionHasSTATUS(tc.cniVersion) { + err := testutils.CmdStatus(func() error { + return cmdStatus(&skel.CmdArgs{StdinData: []byte(tc.netConfJSON(dataDir))}) + }) + Expect(err).NotTo(HaveOccurred()) + } + r, raw, err := testutils.CmdAddWithArgs(tester.args, func() error { return cmdAdd(tester.args) }) diff --git a/plugins/main/dummy/dummy.go b/plugins/main/dummy/dummy.go index ab12642c3..9a2ba0c9e 100644 --- a/plugins/main/dummy/dummy.go +++ b/plugins/main/dummy/dummy.go @@ -181,11 +181,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("dummy")) } @@ -295,3 +295,16 @@ func validateCniContainerInterface(intf current.Interface) error { return nil } + +func cmdStatus(args *skel.CmdArgs) error { + conf := types.NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + + return nil +} diff --git a/plugins/main/dummy/dummy_test.go b/plugins/main/dummy/dummy_test.go index dba70d4d3..594c5cac0 100644 --- a/plugins/main/dummy/dummy_test.go +++ b/plugins/main/dummy/dummy_test.go @@ -106,7 +106,7 @@ type ( func newTesterByVersion(version string) tester { switch { - case strings.HasPrefix(version, "1.0."): + case strings.HasPrefix(version, "1."): return &testerV10x{} case strings.HasPrefix(version, "0.4."): return &testerV04x{} @@ -261,6 +261,13 @@ var _ = Describe("dummy Operations", func() { defer GinkgoRecover() var err error + if testutils.SpecVersionHasSTATUS(ver) { + err = testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) diff --git a/plugins/main/host-device/host-device.go b/plugins/main/host-device/host-device.go index fe807994f..6cd8640f0 100644 --- a/plugins/main/host-device/host-device.go +++ b/plugins/main/host-device/host-device.go @@ -551,11 +551,11 @@ func getLink(devname, hwaddr, kernelpath, pciaddr string, auxDev string) (netlin func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("host-device")) } @@ -663,3 +663,20 @@ func validateCniContainerInterface(intf current.Interface) error { return nil } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if conf.IPAM.Type != "" { + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + } + + // TODO: Check if host device exists. + + return nil +} diff --git a/plugins/main/host-device/host-device_test.go b/plugins/main/host-device/host-device_test.go index f33fd89c2..d2f2b2354 100644 --- a/plugins/main/host-device/host-device_test.go +++ b/plugins/main/host-device/host-device_test.go @@ -231,7 +231,7 @@ type ( func newTesterByVersion(version string) tester { switch { - case strings.HasPrefix(version, "1.0."): + case strings.HasPrefix(version, "1."): return &testerV10x{} case strings.HasPrefix(version, "0.4."): return &testerV04x{} @@ -362,6 +362,15 @@ var _ = Describe("base functionality", func() { "type": "host-device", "device": %q }`, ver, ifname) + + // if v1.1 or greater, call CmdStatus + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(&skel.CmdArgs{StdinData: []byte(conf)}) + }) + Expect(err).NotTo(HaveOccurred()) + } + args := &skel.CmdArgs{ ContainerID: "dummy", Netns: targetNS.Path(), diff --git a/plugins/main/ipvlan/ipvlan.go b/plugins/main/ipvlan/ipvlan.go index 3adb776a8..37736fd2c 100644 --- a/plugins/main/ipvlan/ipvlan.go +++ b/plugins/main/ipvlan/ipvlan.go @@ -351,11 +351,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("ipvlan")) } @@ -491,3 +491,19 @@ func validateCniContainerInterface(intf current.Interface, modeExpected string) return nil } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + if conf.IPAM.Type != "" { + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + } + + // TODO: Check if master interface exists. + + return nil +} diff --git a/plugins/main/ipvlan/ipvlan_test.go b/plugins/main/ipvlan/ipvlan_test.go index eab72a95d..09b1dc64d 100644 --- a/plugins/main/ipvlan/ipvlan_test.go +++ b/plugins/main/ipvlan/ipvlan_test.go @@ -114,6 +114,13 @@ func ipvlanAddCheckDelTest(conf, masterName string, originalNS, targetNS ns.NetN err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() + if testutils.SpecVersionHasSTATUS(cniVersion) { + err = testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) @@ -214,7 +221,7 @@ type ( func newTesterByVersion(version string) tester { switch { - case strings.HasPrefix(version, "1.0."): + case strings.HasPrefix(version, "1."): return &testerV10x{} case strings.HasPrefix(version, "0.4.") || strings.HasPrefix(version, "0.3."): return &testerV04x{} diff --git a/plugins/main/macvlan/macvlan.go b/plugins/main/macvlan/macvlan.go index 6ff918dab..f550be75c 100644 --- a/plugins/main/macvlan/macvlan.go +++ b/plugins/main/macvlan/macvlan.go @@ -429,11 +429,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("macvlan")) } @@ -570,3 +570,20 @@ func validateCniContainerInterface(intf current.Interface, modeExpected string) return nil } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if conf.IPAM.Type != "" { + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + } + + // TODO: Check if master interface exists. + + return nil +} diff --git a/plugins/main/macvlan/macvlan_test.go b/plugins/main/macvlan/macvlan_test.go index 72d84e469..3341acf73 100644 --- a/plugins/main/macvlan/macvlan_test.go +++ b/plugins/main/macvlan/macvlan_test.go @@ -117,7 +117,7 @@ type ( func newTesterByVersion(version string) tester { switch { - case strings.HasPrefix(version, "1.0."): + case strings.HasPrefix(version, "1."): return &testerV10x{} case strings.HasPrefix(version, "0.4."): return &testerV04x{} @@ -322,6 +322,13 @@ var _ = Describe("macvlan Operations", func() { err := originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) @@ -434,6 +441,13 @@ var _ = Describe("macvlan Operations", func() { err := originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) @@ -520,6 +534,13 @@ var _ = Describe("macvlan Operations", func() { defer GinkgoRecover() var err error + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) @@ -660,6 +681,13 @@ var _ = Describe("macvlan Operations", func() { err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) diff --git a/plugins/main/ptp/ptp.go b/plugins/main/ptp/ptp.go index 0ac5e6093..52f755e1d 100644 --- a/plugins/main/ptp/ptp.go +++ b/plugins/main/ptp/ptp.go @@ -301,11 +301,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("ptp")) } @@ -409,3 +409,16 @@ func validateCniContainerInterface(intf current.Interface) error { return nil } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + + return nil +} diff --git a/plugins/main/ptp/ptp_test.go b/plugins/main/ptp/ptp_test.go index bdc78b13e..5caf83f6b 100644 --- a/plugins/main/ptp/ptp_test.go +++ b/plugins/main/ptp/ptp_test.go @@ -105,7 +105,7 @@ type ( func newTesterByVersion(version string) tester { switch { - case strings.HasPrefix(version, "1.0."): + case strings.HasPrefix(version, "1."): return &testerV10x{} case strings.HasPrefix(version, "0.4."): return &testerV04x{} @@ -250,6 +250,14 @@ var _ = Describe("ptp Operations", func() { defer GinkgoRecover() var err error + if testutils.SpecVersionHasSTATUS(cniVersion) { + By("Doing a cni STATUS") + err = testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) diff --git a/plugins/main/tap/tap.go b/plugins/main/tap/tap.go index 057329e96..f789952e0 100644 --- a/plugins/main/tap/tap.go +++ b/plugins/main/tap/tap.go @@ -386,11 +386,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("tap")) } @@ -460,3 +460,18 @@ func cmdCheck(args *skel.CmdArgs) error { return nil }) } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if conf.IPAM.Type != "" { + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + } + + return nil +} diff --git a/plugins/main/tap/tap_test.go b/plugins/main/tap/tap_test.go index f89f066b0..df1ba7656 100644 --- a/plugins/main/tap/tap_test.go +++ b/plugins/main/tap/tap_test.go @@ -108,7 +108,7 @@ type ( func newTesterByVersion(version string) tester { switch { - case strings.HasPrefix(version, "1.0."): + case strings.HasPrefix(version, "1."): return &testerV10x{} case strings.HasPrefix(version, "0.4."): return &testerV04x{} @@ -223,6 +223,13 @@ var _ = Describe("Add, check, remove tap plugin", func() { err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) @@ -364,6 +371,13 @@ var _ = Describe("Add, check, remove tap plugin", func() { err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) diff --git a/plugins/main/vlan/vlan.go b/plugins/main/vlan/vlan.go index b64f7619e..f0e045779 100644 --- a/plugins/main/vlan/vlan.go +++ b/plugins/main/vlan/vlan.go @@ -261,11 +261,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("vlan")) } @@ -399,3 +399,18 @@ func validateCniContainerInterface(intf current.Interface, vlanID int, mtu int) return nil } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + + // TODO: Check if master interface exists. + + return nil +} diff --git a/plugins/main/vlan/vlan_test.go b/plugins/main/vlan/vlan_test.go index d4d435a73..10533cf6e 100644 --- a/plugins/main/vlan/vlan_test.go +++ b/plugins/main/vlan/vlan_test.go @@ -113,7 +113,7 @@ type ( func newTesterByVersion(version string) tester { switch { - case strings.HasPrefix(version, "1.0."): + case strings.HasPrefix(version, "1."): return &testerV10x{} case strings.HasPrefix(version, "0.4."): return &testerV04x{} @@ -354,6 +354,13 @@ var _ = Describe("vlan Operations", func() { defer GinkgoRecover() var err error + if testutils.SpecVersionHasSTATUS(ver) { + err := testutils.CmdStatus(func() error { + return cmdStatus(args) + }) + Expect(err).NotTo(HaveOccurred()) + } + result, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) diff --git a/plugins/main/windows/win-bridge/win-bridge_windows.go b/plugins/main/windows/win-bridge/win-bridge_windows.go index 212a7ade5..dcd2aeba4 100644 --- a/plugins/main/windows/win-bridge/win-bridge_windows.go +++ b/plugins/main/windows/win-bridge/win-bridge_windows.go @@ -216,10 +216,25 @@ func cmdCheck(_ *skel.CmdArgs) error { func main() { skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("win-bridge")) } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if conf.IPAM.Type != "" { + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + } + + return nil +} diff --git a/plugins/main/windows/win-overlay/win-overlay_windows.go b/plugins/main/windows/win-overlay/win-overlay_windows.go index 2a5f842ba..6f8ab9276 100644 --- a/plugins/main/windows/win-overlay/win-overlay_windows.go +++ b/plugins/main/windows/win-overlay/win-overlay_windows.go @@ -106,13 +106,13 @@ func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) { return nil, errors.Annotatef(err, "error while hcn.GetNetworkByName(%s)", networkName) } if hcnNetwork == nil { - return nil, fmt.Errorf("network %v is not found", networkName) + return nil, fmt.Errorf("network %v is not found", networkName) } if hnsNetwork == nil { return nil, fmt.Errorf("network %v not found", networkName) } - if !strings.EqualFold(string (hcnNetwork.Type), "Overlay") { + if !strings.EqualFold(string(hcnNetwork.Type), "Overlay") { return nil, fmt.Errorf("network %v is of an unexpected type: %v", networkName, hcnNetwork.Type) } @@ -131,7 +131,6 @@ func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) { n.ApplyOutboundNatPolicy(hnsNetwork.Subnets[0].AddressPrefix) } hcnEndpoint, err := hns.GenerateHcnEndpoint(epInfo, &n.NetConf) - if err != nil { return nil, errors.Annotate(err, "error while generating HostComputeEndpoint") } @@ -142,15 +141,14 @@ func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) { } result, err := hns.ConstructHcnResult(hcnNetwork, hcnEndpoint) - if err != nil { ipam.ExecDel(n.IPAM.Type, args.StdinData) return nil, errors.Annotate(err, "error while constructing HostComputeEndpoint addition result") } return result, nil - } + func cmdHnsAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) { success := false @@ -243,6 +241,7 @@ func cmdHnsAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) { success = true return result, nil } + func cmdAdd(args *skel.CmdArgs) error { n, cniVersion, err := loadNetConf(args.StdinData) if err != nil { @@ -292,7 +291,20 @@ func main() { Add: cmdAdd, Check: cmdCheck, Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("win-overlay")) } + +func cmdStatus(args *skel.CmdArgs) error { + conf := NetConf{} + if err := json.Unmarshal(args.StdinData, &conf); err != nil { + return fmt.Errorf("failed to load netconf: %w", err) + } + + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + + return nil +} diff --git a/plugins/sample/main.go b/plugins/sample/main.go index 37bdee751..03fc6c613 100644 --- a/plugins/sample/main.go +++ b/plugins/sample/main.go @@ -24,6 +24,7 @@ import ( "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/cni/pkg/version" + "github.com/containernetworking/plugins/pkg/ipam" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -151,11 +152,11 @@ func cmdDel(args *skel.CmdArgs) error { func main() { // replace TODO with your plugin name skel.PluginMainFuncs(skel.CNIFuncs{ - Add: cmdAdd, - Check: cmdCheck, - Del: cmdDel, + Add: cmdAdd, + Check: cmdCheck, + Del: cmdDel, + Status: cmdStatus, /* FIXME GC */ - /* FIXME Status */ }, version.All, bv.BuildString("TODO")) } @@ -163,3 +164,27 @@ func cmdCheck(_ *skel.CmdArgs) error { // TODO: implement return fmt.Errorf("not implemented") } + +// cmdStatus implements the STATUS command, which indicates whether or not +// this plugin is able to accept ADD requests. +// +// If the plugin has external dependencies, such as a daemon +// or chained ipam plugin, it should determine their status. If all is well, +// and an ADD can be successfully processed, return nil +func cmdStatus(args *skel.CmdArgs) error { + conf, err := parseConfig(args.StdinData) + if err != nil { + return err + } + _ = conf + + // If this plugins delegates IPAM, ensure that IPAM is also running + if err := ipam.ExecStatus(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + + // TODO: implement STATUS here + // e.g. querying an external deamon, or delegating STATUS to an IPAM plugin + + return nil +}