func (t AllocatorTestCase) run() (*types.IPConfig, error) { subnet, err := types.ParseCIDR(t.subnet) conf := IPAMConfig{ Name: "test", Type: "host-local", Subnet: types.IPNet{IP: subnet.IP, Mask: subnet.Mask}, } store := fakestore.NewFakeStore(t.ipmap, net.ParseIP(t.lastIP)) alloc, _ := NewIPAllocator(&conf, store) res, err := alloc.Get("ID") return res, err }
// Generates a CNI IPAM config from a given node cluster and local subnet that // CNI 'host-local' IPAM plugin will use to create an IP address lease for the // container func getIPAMConfig(clusterNetwork *net.IPNet, localSubnet string) ([]byte, error) { nodeNet, err := cnitypes.ParseCIDR(localSubnet) if err != nil { return nil, fmt.Errorf("error parsing node network '%s': %v", localSubnet, err) } type hostLocalIPAM struct { Type string `json:"type"` Subnet cnitypes.IPNet `json:"subnet"` Routes []cnitypes.Route `json:"routes"` } type cniNetworkConfig struct { Name string `json:"name"` Type string `json:"type"` IPAM *hostLocalIPAM `json:"ipam"` } return json.Marshal(&cniNetworkConfig{ Name: "openshift-sdn", Type: "openshift-sdn", IPAM: &hostLocalIPAM{ Type: "host-local", Subnet: cnitypes.IPNet{ IP: nodeNet.IP, Mask: nodeNet.Mask, }, Routes: []cnitypes.Route{ { Dst: net.IPNet{ IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero), }, GW: netutils.GenerateDefaultGateway(nodeNet), }, {Dst: *clusterNetwork}, }, }, }) }
"10.0.0.2": "id", }, expectResult: "10.0.0.3", lastIP: "10.0.0.128", }, } for _, tc := range testCases { res, err := tc.run() Expect(err).ToNot(HaveOccurred()) Expect(res.IP.IP.String()).To(Equal(tc.expectResult)) } }) It("should not allocate the broadcast address", func() { subnet, err := types.ParseCIDR("192.168.1.0/24") Expect(err).ToNot(HaveOccurred()) conf := IPAMConfig{ Name: "test", Type: "host-local", Subnet: types.IPNet{IP: subnet.IP, Mask: subnet.Mask}, } store := fakestore.NewFakeStore(map[string]string{}, net.ParseIP("")) alloc, err := NewIPAllocator(&conf, store) Expect(err).ToNot(HaveOccurred()) for i := 1; i < 254; i++ { res, err := alloc.Get("ID") Expect(err).ToNot(HaveOccurred()) // i+1 because the gateway address is skipped
}, expectResult: "10.0.0.3", lastIP: "10.0.0.128", }, } for _, tc := range testCases { res, err := tc.run() Expect(err).ToNot(HaveOccurred()) Expect(res.IP.IP.String()).To(Equal(tc.expectResult)) } }) Context("when requesting a specific IP", func() { It("must allocate the requested IP", func() { subnet, err := types.ParseCIDR("10.0.0.0/29") Expect(err).ToNot(HaveOccurred()) requestedIP := net.ParseIP("10.0.0.2") ipmap := map[string]string{} conf := IPAMConfig{ Name: "test", Type: "host-local", Subnet: types.IPNet{IP: subnet.IP, Mask: subnet.Mask}, Args: &IPAMArgs{IP: requestedIP}, } store := fakestore.NewFakeStore(ipmap, nil) alloc, _ := NewIPAllocator(&conf, store) res, err := alloc.Get("ID") Expect(err).ToNot(HaveOccurred()) Expect(res.IP.IP.String()).To(Equal(requestedIP.String())) })