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 }
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 s := fmt.Sprintf("192.168.1.%d/24", i+1) Expect(s).To(Equal(res.IP.String())) } _, err = alloc.Get("ID") Expect(err).To(HaveOccurred()) })
} }) 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())) }) }) }) Context("when out of ips", func() { It("returns a meaningful error", func() { testCases := []AllocatorTestCase{ { subnet: "10.0.0.0/30", ipmap: map[string]string{ "10.0.0.2": "id",