diff --git a/plugins/ipam/host-local/backend/allocator/config.go b/plugins/ipam/host-local/backend/allocator/config.go index 936b0979..a5ea3b08 100644 --- a/plugins/ipam/host-local/backend/allocator/config.go +++ b/plugins/ipam/host-local/backend/allocator/config.go @@ -21,6 +21,8 @@ import ( "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/version" + + "github.com/containernetworking/plugins/pkg/ip" ) // The top-level network config - IPAM plugins are passed the full configuration @@ -29,8 +31,10 @@ type Net struct { Name string `json:"name"` CNIVersion string `json:"cniVersion"` IPAM *IPAMConfig `json:"ipam"` - RuntimeConfig struct { // The capability arg + RuntimeConfig struct { + // The capability arg IPRanges []RangeSet `json:"ipRanges,omitempty"` + IPs []*ip.IP `json:"ips,omitempty"` } `json:"runtimeConfig,omitempty"` Args *struct { A *IPAMArgs `json:"cni"` @@ -48,7 +52,7 @@ type IPAMConfig struct { DataDir string `json:"dataDir"` ResolvConf string `json:"resolvConf"` Ranges []RangeSet `json:"ranges"` - IPArgs []net.IP `json:"-"` // Requested IPs from CNI_ARGS and args + IPArgs []net.IP `json:"-"` // Requested IPs from CNI_ARGS, args and capabilities } type IPAMEnvArgs struct { @@ -80,7 +84,8 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) { return nil, "", fmt.Errorf("IPAM config missing 'ipam' key") } - // Parse custom IP from both env args *and* the top-level args config + // Parse custom IP from env args, the top-level args config and capabilities + // in runtime configuration if envArgs != "" { e := IPAMEnvArgs{} err := types.LoadArgs(envArgs, &e) @@ -97,6 +102,12 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) { n.IPAM.IPArgs = append(n.IPAM.IPArgs, n.Args.A.IPs...) } + if len(n.RuntimeConfig.IPs) > 0 { + for _, i := range n.RuntimeConfig.IPs { + n.IPAM.IPArgs = append(n.IPAM.IPArgs, i.ToIP()) + } + } + for idx := range n.IPAM.IPArgs { if err := canonicalizeIP(&n.IPAM.IPArgs[idx]); err != nil { return nil, "", fmt.Errorf("cannot understand ip: %v", err) diff --git a/plugins/ipam/host-local/backend/allocator/config_test.go b/plugins/ipam/host-local/backend/allocator/config_test.go index 84a0398b..b6d7c1db 100644 --- a/plugins/ipam/host-local/backend/allocator/config_test.go +++ b/plugins/ipam/host-local/backend/allocator/config_test.go @@ -379,4 +379,29 @@ var _ = Describe("IPAM config", func() { _, _, err := LoadIPAMConfig([]byte(input), "") Expect(err).NotTo(HaveOccurred()) }) + + It("Should parse custom IPs from runtime configuration", func() { + input := `{ + "cniVersion": "0.3.1", + "name": "mynet", + "type": "ipvlan", + "master": "foo0", + "runtimeConfig": { + "ips": ["192.168.0.1", "192.168.0.5/24", "2001:db8::1/64"] + }, + "ipam": { + "type": "host-local", + "subnet": "10.1.2.0/24" + } + }` + conf, version, err := LoadIPAMConfig([]byte(input), "") + Expect(err).NotTo(HaveOccurred()) + Expect(version).Should(Equal("0.3.1")) + + Expect(conf.IPArgs).To(Equal([]net.IP{ + net.IPv4(192, 168, 0, 1).To4(), + net.IPv4(192, 168, 0, 5).To4(), + net.ParseIP("2001:db8::1"), + })) + }) })