diff --git a/main/agent.go b/main/agent.go index f9c8ca577..639f52fa2 100644 --- a/main/agent.go +++ b/main/agent.go @@ -31,7 +31,6 @@ func runAgent(opts boshapp.Options, logger logger.Logger) chan error { } app := boshapp.New(logger, fs) - err := app.Setup(opts) if err != nil { logger.Error(mainLogTag, "App setup %s", err.Error()) diff --git a/platform/dummy_platform_test.go b/platform/dummy_platform_test.go index 9d36d8807..478507a42 100644 --- a/platform/dummy_platform_test.go +++ b/platform/dummy_platform_test.go @@ -73,7 +73,7 @@ var _ = Describe("DummyPlatform", func() { err := fs.WriteFileString(settingsFilePath, `{"IP": "1.2.3.4"}`) Expect(err).NotTo(HaveOccurred()) - network, err := platform.GetDefaultNetwork() + network, err := platform.GetDefaultNetwork(false) Expect(err).NotTo(HaveOccurred()) Expect(network.IP).To(Equal("1.2.3.4")) diff --git a/platform/linux_platform_test.go b/platform/linux_platform_test.go index 79722a7c5..89002801c 100644 --- a/platform/linux_platform_test.go +++ b/platform/linux_platform_test.go @@ -4136,15 +4136,17 @@ unit: sectors }) Describe("GetDefaultNetwork", func() { - It("delegates to the defaultNetworkResolver", func() { - defaultNetwork := boshsettings.Network{IP: "1.2.3.4"} - fakeDefaultNetworkResolver.GetDefaultNetworkNetwork = defaultNetwork - - network, err := platform.GetDefaultNetwork() - Expect(err).ToNot(HaveOccurred()) - - Expect(network).To(Equal(defaultNetwork)) - }) + for _, value := range []bool{true, false} { + title := fmt.Sprintf("delegates to the defaultNetworkResolver with input param %t", value) + It(title, func() { + defaultNetwork := boshsettings.Network{} + fakeDefaultNetworkResolver.GetDefaultNetworkNetwork = defaultNetwork + network, err := platform.GetDefaultNetwork(value) + Expect(err).ToNot(HaveOccurred()) + Expect(network).To(Equal(defaultNetwork)) + Expect(fakeDefaultNetworkResolver.GetDefaultNetworkCalledWith).To(Equal(value)) + }) + } }) Describe("GetHostPublicKey", func() { diff --git a/platform/net/arp/arping_test.go b/platform/net/arp/arping_test.go index 322723c36..afe5e65be 100644 --- a/platform/net/arp/arping_test.go +++ b/platform/net/arp/arping_test.go @@ -19,7 +19,7 @@ type failingInterfaceAddress struct{} func (ia failingInterfaceAddress) GetInterfaceName() string { return "eth0" } -func (ia failingInterfaceAddress) GetIP() (string, error) { +func (ia failingInterfaceAddress) GetIP(IsVersion6 bool) (string, error) { return "", errors.New("fake-get-ip-err") } diff --git a/platform/net/default_network_resolver.go b/platform/net/default_network_resolver.go index 4726bdedd..966b9129e 100644 --- a/platform/net/default_network_resolver.go +++ b/platform/net/default_network_resolver.go @@ -38,7 +38,7 @@ func (r defaultNetworkResolver) GetDefaultNetwork(is_ipv6 bool) (boshsettings.Ne } for _, route := range routes { - if !route.IsDefault() { + if !route.IsDefault(is_ipv6) { continue } @@ -46,7 +46,6 @@ func (r defaultNetworkResolver) GetDefaultNetwork(is_ipv6 bool) (boshsettings.Ne if err != nil { ipVersion := 4 - if is_ipv6 { ipVersion = 6 } diff --git a/platform/net/default_network_resolver_test.go b/platform/net/default_network_resolver_test.go index 2ff8ca156..e67988697 100644 --- a/platform/net/default_network_resolver_test.go +++ b/platform/net/default_network_resolver_test.go @@ -45,14 +45,14 @@ var _ = Describe("defaultNetworkResolver", func() { Context("when primary IPv4 exists for the found route", func() { BeforeEach(func() { - ipResolver.GetPrimaryIPv4IPNet = &gonet.IPNet{ + ipResolver.GetPrimaryIPNet = &gonet.IPNet{ IP: gonet.ParseIP("127.0.0.1"), Mask: gonet.CIDRMask(16, 32), } }) It("returns network with primary IPv4 address from associated interface", func() { - network, err := resolver.GetDefaultNetwork() + network, err := resolver.GetDefaultNetwork(false) Expect(err).ToNot(HaveOccurred()) Expect(network).To(Equal(boshsettings.Network{ IP: "127.0.0.1", @@ -64,11 +64,11 @@ var _ = Describe("defaultNetworkResolver", func() { Context("when primary IPv4 does not exist for the found route", func() { BeforeEach(func() { - ipResolver.GetPrimaryIPv4Err = errors.New("fake-get-primary-ipv4-err") + ipResolver.GetPrimaryIPErr = errors.New("fake-get-primary-ipv4-err") }) It("returns error", func() { - network, err := resolver.GetDefaultNetwork() + network, err := resolver.GetDefaultNetwork(false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-primary-ipv4-err")) Expect(network).To(Equal(boshsettings.Network{})) @@ -86,7 +86,7 @@ var _ = Describe("defaultNetworkResolver", func() { }) It("returns error", func() { - network, err := resolver.GetDefaultNetwork() + network, err := resolver.GetDefaultNetwork(false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Failed to find default route")) Expect(network).To(Equal(boshsettings.Network{})) @@ -99,7 +99,7 @@ var _ = Describe("defaultNetworkResolver", func() { }) It("returns error if there are no routes", func() { - network, err := resolver.GetDefaultNetwork() + network, err := resolver.GetDefaultNetwork(false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("No routes")) Expect(network).To(Equal(boshsettings.Network{})) @@ -112,7 +112,7 @@ var _ = Describe("defaultNetworkResolver", func() { }) It("returns error if searching routes fails", func() { - network, err := resolver.GetDefaultNetwork() + network, err := resolver.GetDefaultNetwork(false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-search-routes-err")) Expect(network).To(Equal(boshsettings.Network{})) diff --git a/platform/net/fakes/fake_default_network_resolver.go b/platform/net/fakes/fake_default_network_resolver.go index 222c46625..1f9919310 100644 --- a/platform/net/fakes/fake_default_network_resolver.go +++ b/platform/net/fakes/fake_default_network_resolver.go @@ -5,12 +5,14 @@ import ( ) type FakeDefaultNetworkResolver struct { - GetDefaultNetworkNetwork boshsettings.Network - GetDefaultNetworkErr error - GetDefaultNetworkCalled bool + GetDefaultNetworkNetwork boshsettings.Network + GetDefaultNetworkErr error + GetDefaultNetworkCalled bool + GetDefaultNetworkCalledWith bool } -func (r *FakeDefaultNetworkResolver) GetDefaultNetwork() (boshsettings.Network, error) { +func (r *FakeDefaultNetworkResolver) GetDefaultNetwork(isIpv6 bool) (boshsettings.Network, error) { r.GetDefaultNetworkCalled = true + r.GetDefaultNetworkCalledWith = isIpv6 return r.GetDefaultNetworkNetwork, r.GetDefaultNetworkErr } diff --git a/platform/net/ip/fakes/fake_ip_resolver.go b/platform/net/ip/fakes/fake_ip_resolver.go index 7e4d676c7..49d530867 100644 --- a/platform/net/ip/fakes/fake_ip_resolver.go +++ b/platform/net/ip/fakes/fake_ip_resolver.go @@ -1,16 +1,20 @@ package fakes import ( + "fmt" gonet "net" ) type FakeResolver struct { GetPrimaryIPInterfaceName string - GetPrimaryIPIPNet *gonet.IPNet + GetPrimaryIPNet *gonet.IPNet GetPrimaryIPErr error + GetPrimaryIPCalledWith []string } func (r *FakeResolver) GetPrimaryIP(interfaceName string, is_ipv6 bool) (*gonet.IPNet, error) { r.GetPrimaryIPInterfaceName = interfaceName - return r.GetPrimaryIPIPNet, r.GetPrimaryIPErr + r.GetPrimaryIPCalledWith = append(r.GetPrimaryIPCalledWith, interfaceName) + r.GetPrimaryIPCalledWith = append(r.GetPrimaryIPCalledWith, fmt.Sprintf("%t", is_ipv6)) + return r.GetPrimaryIPNet, r.GetPrimaryIPErr } diff --git a/platform/net/ip/interface_address_test.go b/platform/net/ip/interface_address_test.go index 9ef144608..e0e6e2bbe 100644 --- a/platform/net/ip/interface_address_test.go +++ b/platform/net/ip/interface_address_test.go @@ -2,6 +2,7 @@ package ip_test import ( "errors" + "fmt" gonet "net" . "github.com/onsi/ginkgo/v2" @@ -14,23 +15,23 @@ import ( var _ = Describe("simpleInterfaceAddress", func() { Describe("GetIP", func() { It("returns fully formatted IPv4", func() { - ipStr, err := NewSimpleInterfaceAddress("iface", "127.0.0.1").GetIP() + ipStr, err := NewSimpleInterfaceAddress("iface", "127.0.0.1").GetIP(false) Expect(err).ToNot(HaveOccurred()) Expect(ipStr).To(Equal("127.0.0.1")) }) It("returns fully formatted IPv6", func() { - ipStr, err := NewSimpleInterfaceAddress("iface", "ff00:f8::").GetIP() + ipStr, err := NewSimpleInterfaceAddress("iface", "ff00:f8::").GetIP(true) Expect(err).ToNot(HaveOccurred()) Expect(ipStr).To(Equal("ff00:00f8:0000:0000:0000:0000:0000:0000")) - ipStr, err = NewSimpleInterfaceAddress("iface", "1101:2202:3303:4404:5505:6606:7707:8808").GetIP() + ipStr, err = NewSimpleInterfaceAddress("iface", "1101:2202:3303:4404:5505:6606:7707:8808").GetIP(true) Expect(err).ToNot(HaveOccurred()) Expect(ipStr).To(Equal("1101:2202:3303:4404:5505:6606:7707:8808")) }) It("returns error if IP cannot be parsed", func() { - _, err := NewSimpleInterfaceAddress("iface", "").GetIP() + _, err := NewSimpleInterfaceAddress("iface", "").GetIP(false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(Equal("Cannot parse IP ''")) }) @@ -51,37 +52,37 @@ var _ = Describe("resolvingInterfaceAddress", func() { Describe("GetIP", func() { Context("when IP was not yet resolved", func() { BeforeEach(func() { - ipResolver.GetPrimaryIPv4IPNet = &gonet.IPNet{ + ipResolver.GetPrimaryIPNet = &gonet.IPNet{ IP: gonet.ParseIP("127.0.0.1"), Mask: gonet.CIDRMask(16, 32), } }) It("resolves the IP and returns fully formatted IPv4", func() { - ip, err := interfaceAddress.GetIP() + ip, err := interfaceAddress.GetIP(false) Expect(err).ToNot(HaveOccurred()) Expect(ip).To(Equal("127.0.0.1")) - Expect(ipResolver.GetPrimaryIPv4InterfaceName).To(Equal("fake-iface-name")) + Expect(ipResolver.GetPrimaryIPInterfaceName).To(Equal("fake-iface-name")) }) It("resolves the IP and returns fully formatted IPv6", func() { - ipResolver.GetPrimaryIPv4IPNet = &gonet.IPNet{ + ipResolver.GetPrimaryIPNet = &gonet.IPNet{ IP: gonet.ParseIP("ff00:f8::"), Mask: gonet.CIDRMask(64, 128), } - ip, err := interfaceAddress.GetIP() + ip, err := interfaceAddress.GetIP(false) Expect(err).ToNot(HaveOccurred()) Expect(ip).To(Equal("ff00:00f8:0000:0000:0000:0000:0000:0000")) - Expect(ipResolver.GetPrimaryIPv4InterfaceName).To(Equal("fake-iface-name")) + Expect(ipResolver.GetPrimaryIPInterfaceName).To(Equal("fake-iface-name")) }) It("returns error if resolving IP fails", func() { - ipResolver.GetPrimaryIPv4Err = errors.New("fake-get-primary-ipv4-err") + ipResolver.GetPrimaryIPErr = errors.New("fake-get-primary-ipv4-err") - ip, err := interfaceAddress.GetIP() + ip, err := interfaceAddress.GetIP(false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-primary-ipv4-err")) Expect(ip).To(Equal("")) @@ -90,24 +91,44 @@ var _ = Describe("resolvingInterfaceAddress", func() { Context("when IP was already resolved", func() { BeforeEach(func() { - ipResolver.GetPrimaryIPv4IPNet = &gonet.IPNet{ + ipResolver.GetPrimaryIPNet = &gonet.IPNet{ IP: gonet.ParseIP("127.0.0.1"), Mask: gonet.CIDRMask(16, 32), } - _, err := interfaceAddress.GetIP() + _, err := interfaceAddress.GetIP(false) Expect(err).ToNot(HaveOccurred()) }) It("does not attempt to resolve IP again", func() { - ipResolver.GetPrimaryIPv4InterfaceName = "" + ipResolver.GetPrimaryIPInterfaceName = "" - ip, err := interfaceAddress.GetIP() + ip, err := interfaceAddress.GetIP(false) Expect(err).ToNot(HaveOccurred()) Expect(ip).To(Equal("127.0.0.1")) - Expect(ipResolver.GetPrimaryIPv4InterfaceName).To(Equal("")) + Expect(ipResolver.GetPrimaryIPInterfaceName).To(Equal("")) }) }) + + Context("when GetIP was called with true or false", func() { + + BeforeEach(func() { + ipResolver.GetPrimaryIPNet = &gonet.IPNet{ + IP: gonet.ParseIP("127.0.0.1"), + Mask: gonet.CIDRMask(16, 32), + } + }) + + for _, value := range []bool{true, false} { + valueStr := fmt.Sprintf("%t", value) + It("it should have been called ipResolver with same value: "+valueStr, func() { + _, err := interfaceAddress.GetIP(value) + Expect(err).ToNot(HaveOccurred()) + Expect(ipResolver.GetPrimaryIPCalledWith).To(Equal([]string{"fake-iface-name", valueStr})) + }) + } + + }) }) }) diff --git a/platform/net/ip/interface_addresses_provider_test.go b/platform/net/ip/interface_addresses_provider_test.go index adcfadd3a..8987018f2 100644 --- a/platform/net/ip/interface_addresses_provider_test.go +++ b/platform/net/ip/interface_addresses_provider_test.go @@ -22,7 +22,7 @@ var _ = Describe("InterfaceAddressesProvider", func() { var loopBackInterface InterfaceAddress for _, iface := range ifaces { - ip, err := iface.GetIP() + ip, err := iface.GetIP(false) Expect(err).ToNot(HaveOccurred()) if ip == "127.0.0.1" { diff --git a/platform/net/ip/ip_resolver.go b/platform/net/ip/ip_resolver.go index ca20288eb..e8a7f097c 100644 --- a/platform/net/ip/ip_resolver.go +++ b/platform/net/ip/ip_resolver.go @@ -40,26 +40,38 @@ func (r ipResolver) GetPrimaryIP(interfaceName string, is_ipv6 bool) (*gonet.IPN return nil, bosherr.Errorf("No addresses found for interface '%s'", interfaceName) } + var foundNonGlobalUniCast *gonet.IPNet + for _, addr := range addrs { ip, ok := addr.(*gonet.IPNet) + if !ok { continue } - if is_ipv6 { - if ip.IP.To16() != nil || ip.IP.IsGlobalUnicast() { - return ip, nil - } - } else { - if ip.IP.To4() != nil || ip.IP.IsGlobalUnicast() { + if ip.IP.To16() != nil && ip.IP.IsGlobalUnicast() && is_ipv6 { + return ip, nil + } + + if ip.IP.To4() != nil && !is_ipv6 { + if ip.IP.IsGlobalUnicast() { return ip, nil + } else { + if foundNonGlobalUniCast == nil { + foundNonGlobalUniCast = ip + } } } } + ipVersion := 4 if is_ipv6 { ipVersion = 6 - } + } + + if foundNonGlobalUniCast != nil { + return foundNonGlobalUniCast, nil + } return nil, bosherr.Errorf("Failed to find primary address IPv%d for interface '%s'", ipVersion, interfaceName) } diff --git a/platform/net/ip/ip_resolver_test.go b/platform/net/ip/ip_resolver_test.go index 9df3e7355..46b8f6ccb 100644 --- a/platform/net/ip/ip_resolver_test.go +++ b/platform/net/ip/ip_resolver_test.go @@ -29,7 +29,7 @@ var _ = Describe("ipResolver", func() { ipResolver = NewResolver(ifaceToAddrs) }) - Describe("GetPrimaryIPv4", func() { + Describe("GetPrimaryIP", func() { Context("when interface exists", func() { It("returns first ipv4 address from associated interface", func() { addrs = []gonet.Addr{ @@ -40,11 +40,25 @@ var _ = Describe("ipResolver", func() { &gonet.IPNet{IP: gonet.ParseIP("127.0.0.10"), Mask: gonet.CIDRMask(24, 32)}, } - ip, err := ipResolver.GetPrimaryIPv4("fake-iface-name") + ip, err := ipResolver.GetPrimaryIP("fake-iface-name", false) Expect(err).ToNot(HaveOccurred()) Expect(ip.String()).To(Equal("127.0.0.1/16")) }) + It("returns first non-local ipv4 address if available from associated interface", func() { + addrs = []gonet.Addr{ + NotIPNet{}, + &gonet.IPNet{IP: gonet.IPv6linklocalallrouters}, + &gonet.IPNet{IP: gonet.ParseIP("ff::"), Mask: gonet.CIDRMask(64, 128)}, + &gonet.IPNet{IP: gonet.ParseIP("127.0.0.1"), Mask: gonet.CIDRMask(16, 32)}, + &gonet.IPNet{IP: gonet.ParseIP("10.0.0.1"), Mask: gonet.CIDRMask(16, 32)}, + } + + ip, err := ipResolver.GetPrimaryIP("fake-iface-name", false) + Expect(err).ToNot(HaveOccurred()) + Expect(ip.String()).To(Equal("10.0.0.1/16")) + }) + It("returns first non-local ipv6 address if available from associated interface", func() { addrs = []gonet.Addr{ NotIPNet{}, @@ -53,7 +67,7 @@ var _ = Describe("ipResolver", func() { &gonet.IPNet{IP: gonet.ParseIP("127.0.0.1"), Mask: gonet.CIDRMask(16, 32)}, } - ip, err := ipResolver.GetPrimaryIPv4("fake-iface-name") + ip, err := ipResolver.GetPrimaryIP("fake-iface-name", true) Expect(err).ToNot(HaveOccurred()) Expect(ip.String()).To(Equal("ff::/64")) }) @@ -61,7 +75,7 @@ var _ = Describe("ipResolver", func() { It("returns error if associated interface does not have any addresses", func() { addrs = []gonet.Addr{} - ip, err := ipResolver.GetPrimaryIPv4("fake-iface-name") + ip, err := ipResolver.GetPrimaryIP("fake-iface-name", false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("No addresses found for interface")) Expect(ip).To(BeNil()) @@ -70,18 +84,18 @@ var _ = Describe("ipResolver", func() { It("returns error if associated interface only has non-IPNet addresses", func() { addrs = []gonet.Addr{NotIPNet{}} - ip, err := ipResolver.GetPrimaryIPv4("fake-iface-name") + ip, err := ipResolver.GetPrimaryIP("fake-iface-name", true) Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Failed to find primary address for interface")) + Expect(err.Error()).To(ContainSubstring("Failed to find primary address IPv6 for interface 'fake-iface-name'")) Expect(ip).To(BeNil()) }) It("returns error if associated interface only has ipv6 addresses", func() { addrs = []gonet.Addr{&gonet.IPNet{IP: gonet.IPv6linklocalallrouters}} - ip, err := ipResolver.GetPrimaryIPv4("fake-iface-name") + ip, err := ipResolver.GetPrimaryIP("fake-iface-name", false) Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Failed to find primary address for interface")) + Expect(err.Error()).To(ContainSubstring("Failed to find primary address IPv4 for interface 'fake-iface-name'")) Expect(ip).To(BeNil()) }) }) @@ -90,7 +104,7 @@ var _ = Describe("ipResolver", func() { It("returns error", func() { funcError = errors.New("fake-network-func-error") - ip, err := ipResolver.GetPrimaryIPv4("whatever") + ip, err := ipResolver.GetPrimaryIP("whatever", false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-network-func-error")) Expect(err.Error()).To(ContainSubstring("Looking up addresses for interface")) diff --git a/platform/net/routes_searcher_interface.go b/platform/net/routes_searcher_interface.go index 53b33df5a..c34a73b7b 100644 --- a/platform/net/routes_searcher_interface.go +++ b/platform/net/routes_searcher_interface.go @@ -12,7 +12,11 @@ type RoutesSearcher interface { } const DefaultAddress = `0.0.0.0` +const DefaultAddressIpv6 = `::` -func (r Route) IsDefault() bool { +func (r Route) IsDefault(isIpv6 bool) bool { + if isIpv6 { + return r.Destination == DefaultAddressIpv6 + } return r.Destination == DefaultAddress } diff --git a/platform/net/routes_searcher_interface_test.go b/platform/net/routes_searcher_interface_test.go index 15b69682d..bfc0c7ff6 100644 --- a/platform/net/routes_searcher_interface_test.go +++ b/platform/net/routes_searcher_interface_test.go @@ -10,12 +10,16 @@ import ( var _ = Describe("Route", func() { Describe("IsDefault", func() { It("returns true if destination is 0.0.0.0", func() { - Expect(Route{Destination: "0.0.0.0"}.IsDefault()).To(BeTrue()) + Expect(Route{Destination: "0.0.0.0"}.IsDefault(false)).To(BeTrue()) + }) + + It("returns true if destination is ::", func() { + Expect(Route{Destination: "::"}.IsDefault(true)).To(BeTrue()) }) It("returns false if destination is not 0.0.0.0", func() { - Expect(Route{}.IsDefault()).To(BeFalse()) - Expect(Route{Destination: "1.1.1.1"}.IsDefault()).To(BeFalse()) + Expect(Route{}.IsDefault(false)).To(BeFalse()) + Expect(Route{Destination: "1.1.1.1"}.IsDefault(false)).To(BeFalse()) }) }) }) diff --git a/platform/net/routes_searcher_unix.go b/platform/net/routes_searcher_unix.go index ad427338b..eb77ab4ff 100644 --- a/platform/net/routes_searcher_unix.go +++ b/platform/net/routes_searcher_unix.go @@ -27,7 +27,7 @@ func NewRoutesSearcher(logger boshlog.Logger, runner boshsys.CmdRunner, _ Interf } func parseRoute(ipString string) (Route, error) { - var r = regexp.MustCompile(`(?P[a-z0-9.]+)(/[0-9]+)?( via (?P[0-9.]+))? dev (?P[a-z0-9]+)`) + var r = regexp.MustCompile(`(?P[a-z0-9.:]+)(/[0-9]+)?( via (?P[a-f0-9.:]+))? dev (?P[a-z0-9]+)`) match := r.FindStringSubmatch(ipString) if len(match) == 0 { @@ -37,14 +37,22 @@ func parseRoute(ipString string) (Route, error) { for i, name := range r.SubexpNames() { matches[name] = match[i] } - gateway := DefaultAddress - if len(matches["gateway"]) > 0 { - gateway = matches["gateway"] - } destination := matches["destination"] + gateway := matches["gateway"] + + defaultGateway := DefaultAddress + + if strings.Contains(destination, ":") || strings.Contains(gateway, ":") { + defaultGateway = DefaultAddressIpv6 + } + + if len(gateway) == 0 { + gateway = defaultGateway + } + if destination == "default" { - destination = DefaultAddress + destination = defaultGateway } return Route{ diff --git a/platform/net/routes_searcher_unix_test.go b/platform/net/routes_searcher_unix_test.go index fc3c818ab..c2539b70c 100644 --- a/platform/net/routes_searcher_unix_test.go +++ b/platform/net/routes_searcher_unix_test.go @@ -36,7 +36,7 @@ default via 172.16.79.1 dev eth0 proto dhcp metric 100 `, }) - routes, err := searcher.SearchRoutes() + routes, err := searcher.SearchRoutes(false) Expect(err).ToNot(HaveOccurred()) Expect(runner.RunCommandsQuietly[0]).To(Equal([]string{"ip", "r"})) Expect(routes).To(Equal([]Route{ @@ -55,7 +55,7 @@ blackhole 10.200.115.192/26 proto bird `, }) - routes, err := searcher.SearchRoutes() + routes, err := searcher.SearchRoutes(false) Expect(err).ToNot(HaveOccurred()) Expect(runner.RunCommandsQuietly[0]).To(Equal([]string{"ip", "r"})) Expect(routes).To(Equal([]Route{ @@ -65,16 +65,50 @@ blackhole 10.200.115.192/26 proto bird })) }) - It("ignores empty lines", func() { + It("ignores empty lines for ipv4", func() { runner.AddCmdResult("ip r", fakesys.FakeCmdResult{ Stdout: ` + `, }) - routes, err := searcher.SearchRoutes() + routes, err := searcher.SearchRoutes(false) Expect(err).ToNot(HaveOccurred()) Expect(routes).To(BeEmpty()) }) + + It("ignores empty lines for ipv6", func() { + runner.AddCmdResult("ip -6 r", fakesys.FakeCmdResult{ + Stdout: ` + +`, + }) + + routes, err := searcher.SearchRoutes(true) + Expect(err).ToNot(HaveOccurred()) + Expect(routes).To(BeEmpty()) + }) + + It("returns parsed routes information for ipv6", func() { + runner.AddCmdResult("ip -6 r", fakesys.FakeCmdResult{ + Stdout: ` +::1 dev lo proto kernel metric 256 pref medium +2600:1f18:58fb:2009::/64 dev eth0 proto ra metric 1024 pref medium +fe80::/64 dev eth0 proto kernel metric 256 pref medium +default via fe80::ceb:d3ff:fef9:fa93 dev eth0 proto ra metric 1024 expires 1796sec pref medium +`, + }) + + routes, err := searcher.SearchRoutes(true) + Expect(err).ToNot(HaveOccurred()) + Expect(routes).To(Equal([]Route{ + Route{Destination: "::1", Gateway: "::", InterfaceName: "lo"}, + Route{Destination: "2600:1f18:58fb:2009::", Gateway: "::", InterfaceName: "eth0"}, + Route{Destination: "fe80::", Gateway: "::", InterfaceName: "eth0"}, + Route{Destination: "::", Gateway: "fe80::ceb:d3ff:fef9:fa93", InterfaceName: "eth0"}, + })) + }) + }) Context("when running ip command fails", func() { @@ -83,7 +117,7 @@ blackhole 10.200.115.192/26 proto bird Error: errors.New("fake-run-err"), }) - routes, err := searcher.SearchRoutes() + routes, err := searcher.SearchRoutes(false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-run-err")) Expect(routes).To(BeEmpty()) diff --git a/platform/net/routes_searcher_windows.go b/platform/net/routes_searcher_windows.go index 7545b8bd9..6519728d6 100644 --- a/platform/net/routes_searcher_windows.go +++ b/platform/net/routes_searcher_windows.go @@ -16,18 +16,22 @@ func NewRoutesSearcher(_ boshlog.Logger, cmdRunner boshsys.CmdRunner, interfaceM } func (s windowsRoutesSearcher) SearchRoutes(ipv6 bool) ([]Route, error) { + var err error + ifs, err := s.interfaceManager.GetInterfaces() if err != nil { return nil, bosherr.WrapError(err, "Running route") } + var defaultGateway string + if ipv6 { - defaultGateway, _, _, err := s.cmdRunner.RunCommandQuietly("(Get-NetRoute -DestinationPrefix '::/0').NextHop") + defaultGateway, _, _, err = s.cmdRunner.RunCommandQuietly("(Get-NetRoute -DestinationPrefix '::/0').NextHop") if err != nil { return nil, bosherr.WrapError(err, "Running IPv6 route") } } else { - defaultGateway, _, _, err := s.cmdRunner.RunCommandQuietly("(Get-NetRoute -DestinationPrefix '0.0.0.0/0').NextHop") + defaultGateway, _, _, err = s.cmdRunner.RunCommandQuietly("(Get-NetRoute -DestinationPrefix '0.0.0.0/0').NextHop") if err != nil { return nil, bosherr.WrapError(err, "Running IPv4 route") } @@ -41,7 +45,7 @@ func (s windowsRoutesSearcher) SearchRoutes(ipv6 bool) ([]Route, error) { } if fs.Gateway == defaultGateway { if ipv6 { - route.Destination = "::/0" // Default route for IPv6 + route.Destination = "::" // Default route for IPv6 } else { route.Destination = "0.0.0.0" // Default route for IPv4 } diff --git a/platform/net/routes_searcher_windows_test.go b/platform/net/routes_searcher_windows_test.go index 29471aa2f..e728c5637 100644 --- a/platform/net/routes_searcher_windows_test.go +++ b/platform/net/routes_searcher_windows_test.go @@ -35,17 +35,39 @@ var _ = Describe("Windows Route Searcher", func() { Stdout: `10.0.16.1`, }) - routes, err := searcher.SearchRoutes() + routes, err := searcher.SearchRoutes(false) Expect(err).NotTo(HaveOccurred()) Expect(routes).To(HaveLen(2)) Expect(routes[0].InterfaceName).To(Equal("some-created-interface")) Expect(routes[0].Gateway).To(Equal("172.30.0.1")) - Expect(routes[0].IsDefault()).To(BeFalse()) + Expect(routes[0].IsDefault(false)).To(BeFalse()) Expect(routes[1].InterfaceName).To(Equal("some-default-interface")) Expect(routes[1].Gateway).To(Equal("10.0.16.1")) - Expect(routes[1].IsDefault()).To(BeTrue()) + Expect(routes[1].IsDefault(false)).To(BeTrue()) + }) + + It("returns default and non-default routes for existing interfaces", func() { + interfaceManager.GetInterfacesInterfaces = []net.Interface{ + {Name: "some-created-interface", Gateway: "2600:1000::1"}, + {Name: "some-default-interface", Gateway: "10.0.16.1"}, + } + runner.AddCmdResult("(Get-NetRoute -DestinationPrefix '::/0').NextHop", fakesys.FakeCmdResult{ + Stdout: `2600:1000::1`, + }) + + routes, err := searcher.SearchRoutes(true) + Expect(err).NotTo(HaveOccurred()) + Expect(routes).To(HaveLen(2)) + + Expect(routes[0].InterfaceName).To(Equal("some-created-interface")) + Expect(routes[0].Gateway).To(Equal("2600:1000::1")) + Expect(routes[0].IsDefault(true)).To(BeTrue()) + + Expect(routes[1].InterfaceName).To(Equal("some-default-interface")) + Expect(routes[1].Gateway).To(Equal("10.0.16.1")) + Expect(routes[1].IsDefault(false)).To(BeFalse()) }) }) }) diff --git a/platform/platformfakes/fake_platform.go b/platform/platformfakes/fake_platform.go index 2512ea3fa..91f3ea77b 100644 --- a/platform/platformfakes/fake_platform.go +++ b/platform/platformfakes/fake_platform.go @@ -1420,7 +1420,7 @@ func (fake *FakePlatform) GetCopierReturnsOnCall(i int, result1 fileutil.Copier) }{result1} } -func (fake *FakePlatform) GetDefaultNetwork() (settings.Network, error) { +func (fake *FakePlatform) GetDefaultNetwork(isIpv6 bool) (settings.Network, error) { fake.getDefaultNetworkMutex.Lock() ret, specificReturn := fake.getDefaultNetworkReturnsOnCall[len(fake.getDefaultNetworkArgsForCall)] fake.getDefaultNetworkArgsForCall = append(fake.getDefaultNetworkArgsForCall, struct { diff --git a/platform/windows_platform_test.go b/platform/windows_platform_test.go index c54878859..69467d1b4 100644 --- a/platform/windows_platform_test.go +++ b/platform/windows_platform_test.go @@ -269,15 +269,17 @@ var _ = Describe("WindowsPlatform", func() { }) Describe("GetDefaultNetwork", func() { - It("delegates to the defaultNetworkResolver", func() { - defaultNetwork := boshsettings.Network{IP: "1.2.3.4"} - fakeDefaultNetworkResolver.GetDefaultNetworkNetwork = defaultNetwork - - network, err := platform.GetDefaultNetwork() - Expect(err).ToNot(HaveOccurred()) - - Expect(network).To(Equal(defaultNetwork)) - }) + for _, value := range []bool{true, false} { + title := fmt.Sprintf("delegates to the defaultNetworkResolver with input param %t", value) + It(title, func() { + defaultNetwork := boshsettings.Network{} + fakeDefaultNetworkResolver.GetDefaultNetworkNetwork = defaultNetwork + network, err := platform.GetDefaultNetwork(value) + Expect(err).ToNot(HaveOccurred()) + Expect(network).To(Equal(defaultNetwork)) + Expect(fakeDefaultNetworkResolver.GetDefaultNetworkCalledWith).To(Equal(value)) + }) + } }) Describe("SetTimeWithNtpServers", func() { diff --git a/settings/settingsfakes/fake_platform_settings_getter.go b/settings/settingsfakes/fake_platform_settings_getter.go index 58a895f4e..cb706fb0a 100644 --- a/settings/settingsfakes/fake_platform_settings_getter.go +++ b/settings/settingsfakes/fake_platform_settings_getter.go @@ -128,7 +128,7 @@ func (fake *FakePlatformSettingsGetter) GetAgentSettingsPathReturnsOnCall(i int, }{result1} } -func (fake *FakePlatformSettingsGetter) GetDefaultNetwork() (settings.Network, error) { +func (fake *FakePlatformSettingsGetter) GetDefaultNetwork(isIpV6 bool) (settings.Network, error) { fake.getDefaultNetworkMutex.Lock() ret, specificReturn := fake.getDefaultNetworkReturnsOnCall[len(fake.getDefaultNetworkArgsForCall)] fake.getDefaultNetworkArgsForCall = append(fake.getDefaultNetworkArgsForCall, struct {